设计模式之工厂方法
1. 定义
在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型
2. 口语化举例
工厂里组装台灯,流程、配件等有多种方式,每种台灯有自己的生产线
现在,需要某一种台灯,但暂时不知道是哪一种,一种方式是想清楚了再去找工厂生产
另一种方式是先去和工厂联系好,支付定金,工厂给出一张购买凭证,想清楚需要什么台灯时,就可以直接兑换
这流程有一定的好处,就是拿到购买凭证过后,我就象征性的拥有了台灯,虽然现在还没有具体实物,拿着这个凭证,可以去干拥有台灯才能干的事,比如零售台灯
这就是工厂方法模式,虽然创建时暂时还没有具体对象,但是拥有随时创建具体对象的能力
(下面的描述会沿用这个上述这个场景)
3. 源码示例
Cesium.js是一个著名的、基于WebGL的GIS前端框架
基于WebGL就不得不提WebGL(OpenGL)的基础概念,比如Shader、Shader Program等
Cesium中有频繁的Shader Program创建操作,源码中封装了ShaderProgram类,其中createAndLinkProgram(gl, shader)
函数实现了创建
Shader Program是多种多样的,所以Cesium将最后实例化的ShaderProgram交给子类来确定
值得一说的是,在Cesium中,真正的ShaderProgram对象是直到需要绘制时才创建,不需要绘制的就不会创建,这样有效节省了资源:
function beginDraw() {
// ...
shaderProgram.createAndLinkProgram(gl, shader);
}
4. 总结
4.1 设计原则
-
单一职责原则
每个生产线只负责生产自己的产品,前台只负责通知调度,职责明确
-
开闭原则
要添加新的产品线只需告诉前台即可
4.2 适用场景
-
无法预知对象确切类别及其依赖关系时, 可使用工厂方法
无法确定具体生产什么,所以需要客户自己确定并告知工厂生产线
-
构建能扩展的软件库或框架的内部组件, 可使用工厂方法
前台的存在使得要添加新的产品线只需告诉前台即可
-
复用现有对象来节省系统资源, 而不是每次都重新创建对象, 可使用工厂方法
前台具有拦截并调度的作用,如果要生产的产品有库存,前台可以直接交付给客户,无需再告诉生产线