工厂模式属于创建型模式,主要分为:简单工厂模式,工厂方法模式,抽象工厂模式
简单工厂模式
主要特点就是需要在工厂类中做判断,从而创造相应的产品,当增加新的产品时,需要修改工厂类。举例,有家生产处理器核的厂家,仅有一家工厂,能生产两种型号的处理器,客户需要什么样的处理器,一定要显式地告诉工厂生产。
例:
1 enum CTYPE {COREA, COREB}; 2 3 class SingleCore { 4 public: 5 virtual void show() = 0; 6 }; 7 8 //单核A 9 class SingleCoreA: public SingleCore { 10 public: 11 void show() { cout << "SingleCore A" << endl; } 12 }; 13 //单核B 14 class SingleCoreB: public SingleCore { 15 public: 16 void show() { cout << "SingleCore B" << endl; } 17 }; 18 19 //唯一的工厂,可以生产两种型号的处理器核,在内部判断 20 class Factory { 21 public: 22 SingleCore* createSingleCore(enum CTYPE core) { 23 if(core == COREA) { 24 return new SingleCoreA(); 25 }else if(core == COREB) { 26 return new SingleCoreB(); 27 }else 28 return nullptr; 29 } 30 };
缺点:
增加新的处理器核类型,需要修改工厂类,违反了开闭原则:对扩展开放,对更改封闭。
因此工厂方法模式出现了,即定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到其子类。
Factory Method
接着举例:这家生产处理器核的厂家赚到飞天,就决定再开设一个工厂专门生产B型号的单核,而原来的工厂专门原来生产A单核。如此,客户有需求就直接找生产对应核的工厂就可以,无须告诉工厂需要什么样的核。
例子:
1 class SingleCore { 2 public: 3 virtual void show() = 0; 4 }; 5 6 //单核A 7 class SingleCoreA: public SingleCore { 8 public: 9 void show() { cout << "SingleCore A" << endl; } 10 }; 11 //单核B 12 class SingleCoreB: public SingleCore { 13 public: 14 void show() { cout << "SingleCore B" << endl; } 15 }; 16 17 class Factory { 18 public: 19 virtual SingleCore* createSingleCore() = 0; 20 }; 21 //生产A核的工厂 22 class FactoryA :public Factory{ 23 public: 24 SingleCoreA* createSingleCore() {return new SingleCoreA();} 25 }; 26 27 //生产B核的工厂 28 class FactoryB :public Factory{ 29 public: 30 SingleCoreB* createSingleCore() {return new SingleCoreB();} 31 };
当然,工厂方法模式也有缺点,新的工厂会随着新产品的增加而增加,会需要很多的类定义。
动机
- 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
- 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?
模式定义
- 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。 ——《设计模式》GoF
要点总结
- Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
- Factory Method模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
- Factory Method模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。
Abstract Factory
随着这家公司技术不断进步,可以生产多核处理器了,抽象工厂模式中,提供一个创建一系列相关或依赖对象的接口,而无须为相关联的不同产品分别指定具体的类。同样,该厂家开设两家工厂,一个专门生产A型号的单核与多核处理器,另一个专门生产B型号的单核与多核处理器。实现如下:
1 class SingleCore { 2 public: 3 virtual void show() = 0; 4 }; 5 6 //单核A 7 class SingleCoreA: public SingleCore { 8 public: 9 void show() { cout << "SingleCore A" << endl; } 10 }; 11 //单核B 12 class SingleCoreB: public SingleCore { 13 public: 14 void show() { cout << "SingleCore B" << endl; } 15 }; 16 17 18 //多核 19 class MultiCore { 20 public: 21 virtual void show() = 0; 22 }; 23 24 class MultiCoreA: public MultiCore { 25 public: 26 void show() { cout << "MultiCore A" << endl; } 27 }; 28 29 class MultiCoreB: public MultiCore { 30 public: 31 void show() { cout << "MultiCore B" << endl; } 32 }; 33 34 //工厂 35 class Factory { 36 public: 37 virtual SingleCore* createSingleCore() = 0; 38 virtual MultiCore* createMultliCore() = 0; 39 }; 40 41 //工厂A,专门用来生产A型号的处理器 42 class FactoryA :public Factory{ 43 public: 44 SingleCore* createSingleCore() {return new SingleCoreA();} 45 MultiCore* createMultiCore() { return new MultiCoreA(); } 46 }; 47 48 //工厂B,专门用来生产B型号的处理器 49 class FactoryB :public Factory{ 50 public: 51 SingleCore* createSingleCore() {return new SingleCoreB();} 52 MultiCore* createMultiCore() { return new MultiCoreB(); } 53 54 };
动机
- 在软件系统中,经常面临着“一系列相互依赖的对象工作”;同时,由于需求的变化,往往存在更多系列对象的创建工作。
- 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合。
模式定义
- 提供一个接口,让该接口负责创建一系列”相关或者相互依赖的对象“,无需指定它们具体的类。 ——《设计模式》GoF
要点总结
- 如果没有应对”多系列对象创建“的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂即可。
- ”系列对象“指的是在某一个特定系列的对象之间有相互依赖、或作用的关系。不同系列的对象之间不能相互依赖。
- Abstract Factory模式主要在于应用”新系列“的需求变动。其缺点在与难以应对”新对象“的需求变动。