工厂方法模式的定义
定义: 定义一个用于创建对象的接口,让子类决定实例化哪一个类. 工厂方法使一个类的实例化延迟到其子类
工厂方法模式的通用类图:
其中 Product 负责产品的共性,实现对事物最抽象的定义; Creator 为抽象创建类, 也就是抽象工厂, 具体如何创建产品类是由具体的实现工厂 ConcreteCreator 完成的. 下面给出他们的代码:
产品抽象类代码:
具体产品类继承自抽象产品类,抽象工厂负责定义产品对象的产生,代码如下;
具体工厂类的实现代码如下:
工厂方法模式的优点
- 良好的封装性,代码结构清晰. 一个对象创建是有条件约束的, 如一个调用者需要一个具体的产品对象,只要知道产品的类名就可以了, 不用知道对象是如何创建的,降低模块间的耦合
- 工厂方法模式的扩展性非常优秀. 在增加产品类的情况下, 只要适当的修改具体的工厂类或扩展一个工厂类, 就可以完成"拥抱变化".
- 屏蔽产品类. 产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口, 只要接口保持不变, 系统中的上层模块就不用发生变化. 因为产品类的实例化是由工厂类负责的,一个产品对象具体由哪一个产品生成是由工厂类决定的.
- 工厂方法模式是典型的解耦框架. 高层模块只需要知道产品的抽象类, 其他的实现类都不用关心.
工厂方法模式的使用场景
- 工厂方法模式是new一个对象的替代品,所以在所有需要生成对象的地方都可以使用,但是要考虑是否要增加一个工厂类进行管理,增加代码复杂度
- 需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式.
- 工厂方法模式可以用在异构项目中,
- 可以使用在测试驱动开发的框架下. 例如, 测试一个类A,就需要把与类A有关联关系的类B也同时生产出来,我们可以使用工厂方法模式把类B虚拟出来,避免类A与类B的耦合.
工厂方法模式的扩展
工厂方法模式有很多扩展,而且与其他模式结合使用威力更大,下面介绍四种扩展
1.缩小为简单工厂模式
一个模块仅需要一个工厂类,那就没有必要把他产生出来,使用静态方法就可以了,在使用的时候也就不用将类实例化, 直接使用即可. 调用者也比较简单, 缺点是工厂类的扩展比较困难, 不符合开闭原则
2.升级为多个工厂类
当我们在做一个比较复杂的项目时,经常会遇到初始化一个对象很耗费精力的情况,所有的产品类都放到一个工厂方法中进行初始化会使代码结构不清晰. 考虑到需要结构清晰, 我们为每个产品定义一个创造者, 好处是创建类的职责清晰,而且结构简单, 但是给可扩展性和可维护性带来了一定的影响. 当然, 在复杂的应用中一般采用多工厂的方法, 然后再增加一个协调类, 避免调用者与各个子工厂交流,协调类的作用是封装子工厂类,对高层模块提供统一的访问接口.
3.替代单例模式
当类的构造方法为私有时, 可以通过反射来创建一个实例,然后通过工厂获得该类的唯一实例
4.延迟初始化
就是一个对象被消费完毕后,并不立刻释放,工厂类保持其初始状态,等待再次被使用.
延迟加载框架是可以扩展的, 例如限制某一个产品类的最大实例化数量,可以通过判断Map中已有的对象数量来实现,这样的处理是非常有意义的.
延迟加载还可以用在对象初始化比较复杂的情况下,例如硬件访问,设计多方面的交互,则可以通过延迟加载降低对象的产生和销毁带来的复杂性
工厂方法模式在项目中使用的非常频繁,以至于很多代码中都包含工厂方法模式. 而且工厂方法模式还可以与其它模式混合使用,变化出无穷的优秀设计,这也正是软件设计和开发的乐趣所在.