工厂模式在“创造模式”中是比较难理解的,困难之处并不在于工厂模式的定义本身,困惑的地方在于为什么要使用工厂模式,或者说是必须使用工厂的理由。
工厂模式的定义
Define an interface for creating
an object, but let the classes that implement the interface decide which
class to instantiate.
The Factory method lets a class defer
instantiation to subclasses.
对于使用工厂模式的疑问在于,产品类所定义产品实体是在客户逻辑中真正使用的目标,如果产品类已经抽象,使用者只需要将产品的子类实例化后使用产品的接口或父类,为什么一定要使用工厂类,多此一举。
即使使用工厂类,实际上是工厂的子类去实例化具体的产品,对于使用者来说,去判断使用哪一个工厂和去判断使用哪一个产品没有本质的区别,为什么在设计的时候还需要加入工厂的接口,和工厂的继承类,增加复杂度呢。
关键的问题在于工厂模式定义中的最后一句,工厂的子类决定如何实现子产品,实现局域化和特性化的产品。
产品的实例化,指的是子产品的实例化,子产品在实现的时候,是不是需要有特性化和局域化的需求,成为是否使用工厂模式的判断标准。
更简单的说,如果所有的产品在的实例化只是一个简单的new,可以解决,那使用工厂就完全是多此一举。而各种产品,虽然可以维持统一接口, 但在实例化时是需要不同的,甚至复杂的处理,或者更复杂的逻辑处理,那么,工厂的目的就是,将复杂的不同的实例化逻辑统一成统一的接口,来屏蔽使用者对于实例化产品是对其复杂逻辑的理解与实现,而统一使用简单的工厂接口。
就以图中类为例
class Light{ public: Light(){} virtual void TurnOn() = 0; } class BulbLight : public { public: BulbLight() void TurnOn() { // power 5v } } class TubeLight : public { public: TubeLight(){} void TurnOn(){ // power 220v } }
如果做两个工厂类BulbFactory和TubeFactory对BulbLight和TubeLight进行实例化,使用者仍然需要决定并实现Factory的实例,这同实现具体的Light类没有区别,也没有益处,反而增加工作量和复杂度。
然而,Light子类的构造变得复杂时,情况变不一样了
class BulbLight : public { Power power; public: BulbLight(Power bettery) : power(bettery) {} void Fill(Gas current_gas); void TurnOn() { // power 5v } } class TubeLight : public { Cable wire; public: TubeLight(Cable power) : wire(power) {} void TurnOn(){ // power 220v } }
对于使用者来说,不去向BulbLight和TubeLight的设计者(文档)了解实例化的细节,将很难使用两个子类
这将是Factory的优势所在,Light子类的设计者,同时提供Factory接口的产品实例化方法,屏蔽了产品本身实例化的复杂逻辑
如果实例化之后还有其他本地化的逻辑,如Fill之类,工厂模式的特性会更具体的体现出来。