定义
定义一个创建对象的接口、让子类决定实例化哪一个类, Factory Method 使一个类的实例化延迟到其子类。
结构和说明
示例代码
public class FactoryMethodDemo {public static interface Product {}public static abstract class Creator {protected abstract Product factoryMethod();public void somOperation() {// 通常在这些方法实现中需要调用工厂方法来获取 Product 对象Product product = factoryMethod();}}public static class ConcreteProduct implements Product {}public static class ConcreteCreator extends Creator {@Overrideprotected Product factoryMethod() {return new ConcreteProduct();}}}
这里要注意一个问题,子类在实现这些抽象方法的时候,通常并不是真正地由子类来实现具体的功能,而是在子类的方法里面做选择,选择具体的产品实现对象。
父类里面,通常会有使用这些产品对象来实现一定的功能的方法,而且这些方法所实现的功能通常都是公共的功能,不管子类选择了何种具体的产品实现,这些方法的功能总是能正确执行。
模式讲解
- 谁来使用工厂方法创建的对象
是 Creator 中的其他方法在使用工厂方法创建的对象,虽然也可以把工厂方法创建的对象直接提供给 Creator 外部使用,但工厂方法模式的本意可,是由 Creator 对象内部的方法来使用工厂方法创建的对象,也就是说,工厂方法一般不提供给 Creator 外部使用。
客户端应该使用 Creator 对象,或者使用由 Creator 创建出来的对象。对于客户端使用 Creator 对象,这个时候工厂方法创建出来的对象,这个时候工厂方法创建出来的对象,是 Creator 中某些方法使用;对于使用那些由 Creator 创建出来的对象,这个时候工厂方法创建的对象,是构成客户端需要的对象的一部分。分别举例说明。
(1) 客户端使用 Creator 对象的情况
/*** 客户端使用 Creator 对象的情况下, Creator 的基本实现*/public abstract class Creator1 {/*** 工厂方法,一般不对外** @return 创建的产品对象*/protected abstract Product factoryMethod();public void someOperation() {// 在这里使用工厂方法Product product = factoryMethod();}}
(2) 客户端使用 Creator 创建出来的对象
/*** 客户端使用 Creator 来创建客户单需要的对象的情况下, Creator 的基本实现*/public abstract class Creator2 {/*** 工厂方法,一般不对外,创建一个部件对象** @return 创建的产品对象,一般是另一个产品对象的部件*/protected abstract Product1 factoryMethod1();/*** 工厂方法,一般不对外,创建一个部件对象** @return 创建的产品对象,一般是另一个产品对象的部件*/protected abstract Product2 factoryMethod2();public Product createProduct() {// 在这里使用工厂方法, 得到客户端所需对象的部件对象Product1 p1 = factoryMethod1();Product2 p2 = factoryMethod2();// 工厂方法创建的对象是创建客户端对象所需要的Product p = new ConcreteProduct();p.setProduct1(p1);p.setProduct2(p2);return p;}}
小结一下: 在工厂方法模式里面,客户端要么使用 Creator 对象,要么使用 Creator 创建的对象,一般客户端不直接使用工厂方法。当然也可以直接把工厂方法暴露给客户端操作,但是一般不这么做。
调用顺序
客户端使用 Creator 对象的情况
客户端使用 Creator 创建出来的对象
参数化工厂
/*** 1. 非抽象*/public static class Creator {/*** 2. 非抽象, 有默认实现** @param type* @return*/protected Product factoryMethod(int type) {// 根据参数来选择 Product 实现return null;}public void someOperatioin(int type) {Product product = factoryMethod(type);}}
优缺点
优点
- 可以在不知具体实现的情况下编程
工厂方法模式可以让你在实现功能的时候,如果需要某个产品对象,只需要使用产品的接口即可,而无须关心具体的实现。选择具体实现的任务延迟到子类去完成。
- 更容易扩展对象的新版本
工厂方法给子类提供了一个挂钩,使得扩展新对象的版本非常容易。
另外这里提到的挂钩,就是我们常说的钩子方法(hook)
- 链接平行的类层次
工厂方法出了创造产品对象外,在链接平行的类层次上也大显身手。
缺点
- 具体产品对象和工厂方法的耦合性
在工厂方法模式中,工厂方法是需要创建产品对象的,也是需要选择具体的产品对象,并创建他们的实例,因此具体产品对象和工厂方法是耦合的。
思考
本质
延迟到子类来选择实现
对设计原则的体现
- 依赖倒置原则
何时选用
- 如果一个类需要创建某个接口的对象,但是又不知道具体的实现,这种情况可以选用工厂方法模式,把创建对象的工作延迟到子类中去实现。
- 如果一个类本身就希望由它的子类来创建所需的对象的时候,应该使用工厂方法模式。
相关模式
- 工厂方法模式和抽象工厂模式
这两个模式可以组合使用,具体的放到抽象工厂模式中去讲。
- 工厂方法模式和模版方法模式
这个模式外观类似,都有一个抽象类,然后由子类去提供一些实现,但是工厂方法模式的子类专注的是创建产品对象,而模版方法的子类专注的是为固定的算法骨架提供某些步骤的实现。
这两个模式可以组合使用,通常在模版方法里面,使用工厂方法来创建模版方法需要的对象。
