一、应用背景
还是以宝马汽车制造为例。
随着客户的要求越来越高,宝马车需要不同配置的空调和发动机等配件。于是这个工厂开始生产空调和发动机,用来组装汽车。这时候工厂有两个系列的产品:空调和发动机。宝马320系列配置A型号空调和A型号发动机,宝马230系列配置B型号空调和B型号发动机。
二、具体例子:
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。比如宝马320系列使用空调型号A和发动机型号A,而宝马230系列使用空调型号B和发动机型号B,那么使用抽象工厂模式,在为320系列生产相关配件时,就无需制定配件的型号,它会自动根据车型生产对应的配件型号A。
三、代码实践
1 /* 2 @author CodingMengmeng 3 @datetime:2016-9-30 10:26:46 4 @description:Abstract Factory Pattern. 5 */ 6 #include7 #include 8 using namespace std; 9 //Engine 10 class CEngine{ 11 public: 12 CEngine() 13 { 14 } 15 ~CEngine() 16 { 17 } 18 virtual void getStyleOfEngine(void) = 0; 19 }; 20 //type A of Engine 21 class CEngineA :public CEngine{ 22 public: 23 CEngineA() 24 { 25 } 26 ~CEngineA() 27 { 28 } 29 30 void getStyleOfEngine() 31 { 32 cout << "Produce -->EngineA" << endl; 33 } 34 }; 35 //type B of Engine 36 class CEngineB :public CEngine{ 37 public: 38 CEngineB() 39 { 40 } 41 ~CEngineB() 42 { 43 } 44 void getStyleOfEngine() 45 { 46 cout << "Produce -->EngineB" << endl; 47 } 48 }; 49 50 51 //Aircondition 52 class CAircondition{ 53 public: 54 CAircondition() 55 { 56 } 57 ~CAircondition() 58 { 59 } 60 virtual void getStyleOfAircondition() = 0; 61 }; 62 63 //type A of Aircondition 64 class CAirconditionA :public CAircondition{ 65 public: 66 CAirconditionA() 67 { 68 } 69 ~CAirconditionA() 70 { 71 } 72 void getStyleOfAircondition() 73 { 74 cout << "Produce -->AirconditionA" << endl; 75 } 76 }; 77 //type B of Aircondition 78 class CAirconditionB :public CAircondition{ 79 public: 80 CAirconditionB() 81 { 82 } 83 ~CAirconditionB() 84 { 85 } 86 void getStyleOfAircondition() 87 { 88 cout << "Produce -->AirconditionB" << endl; 89 } 90 }; 91 92 //Abstract Class Of Factory 93 class CFactoryBMW{ 94 public: 95 CFactoryBMW() 96 { 97 } 98 ~CFactoryBMW() 99 {100 }101 virtual CEngine* createEngine() = 0;102 virtual CAircondition* createAircondition() = 0;103 };104 105 //FactoryBMW Of BMW320106 //Produce Accessories For BMW320107 class CFactoryBMW320 :public CFactoryBMW{108 public:109 CFactoryBMW320()110 {111 }112 ~CFactoryBMW320()113 {114 }115 CEngine* createEngine()116 {117 return new CEngineA();118 }119 CAircondition* createAircondition()120 {121 return new CAirconditionA();122 }123 };124 125 //FactoryBMW Of BMW523126 //Produce Accessories For BMW523127 class CFactoryBMW523 :public CFactoryBMW{128 public:129 CFactoryBMW523()130 {131 }132 ~CFactoryBMW523()133 {134 }135 CEngine* createEngine()136 {137 return new CEngineB();138 }139 CAircondition* createAircondition()140 {141 return new CAirconditionB();142 }143 };144 145 //客户端146 int _tmain(int argc, _TCHAR** argv)147 {148 //About BMW320149 CFactoryBMW* factoryBMW320 = new CFactoryBMW320();150 CEngine* engineA = factoryBMW320->createEngine();151 engineA->getStyleOfEngine();152 CAircondition* airconditionA = factoryBMW320->createAircondition();153 airconditionA->getStyleOfAircondition();154 cout << "**------------------------------------------**" << endl;155 //About BMW523156 CFactoryBMW* factoryBMW523 = new CFactoryBMW523();157 CEngine* engineB = factoryBMW523->createEngine();158 engineB->getStyleOfEngine();159 CAircondition* airconditionB = factoryBMW523->createAircondition();160 airconditionB->getStyleOfAircondition();161 162 return 0;163 }
运行结果:
四、详谈抽象工厂模式
起源:
抽象工厂模式的起源或者最早的应用,是用于创建分属于不同操作系统的视窗构建。比如:命令按键(Button)与文字框(Text)都是视窗构建,在UNIX操作系统的视窗环境和Windows操作系统的视窗环境中,这两个构建有不同的本地实现,它们的细节有所不同。
可以发现在上面的产品类图中,有两个产品的等级结构,分别是Button等级结构和Text等级结构。同时有两个产品族,也就是UNIX产品族和Windows产品族。UNIX产品族由UNIX Button和UNIX Text产品构成;而Windows产品族由Windows Button和Windows Text产品构成。
系统对产品对象的创建需求由一个工程的等级结构满足,其中有两个具体工程角色,即UnixFactory和WindowsFactory。UnixFactory对象负责创建Unix产品族中的产品,而WindowsFactory对象负责创建Windows产品族中的产品。这就是抽象工厂模式的应用,抽象工厂模式的解决方案如下图:
抽象工厂模式定义:
Provide an interface for creating families of related or dependent objects without specifying their concrete classes。 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。
抽象工厂的通用类图如下图所示。
虽然抽象工厂模式的类繁多,但是主要还是分为四类:
1)AbstractFactory:抽象工厂角色,它声明了一组用于创建不同产品的方法(函数),每一个方法对应一种产品,如本文开头对应的发动机产品和空调产品,在抽象工厂角色中对应的方法为:
1 virtual CEngine* createEngine() = 0;2 virtual CAircondition* createAircondition() = 0;
2)ConcreteFactory:具体工厂角色,它实现了在抽象工厂中定义的创建产品的方法,生成一组具体产品,这些产品构成一个产品种类,每一个产品都位于某个产品登记结构中。如文中开头的CFactoryBMW320类,是专门用于生产BMW320车型的所有配件的工厂;CFactoryBMW523类是专门用于生产BMW523车型的所有配件的工厂。
3)AbstractProduct:抽象产品角色(对应抽象类CEngine和CAircondition),它定义了几种产品的基本行为。
4)ConcreteProduct:具体产品角色(对应CEngineA、CEngineB、CAirconditionA和CAirconditionB四个实现类),它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
抽象工厂模式与工厂方法的区别:
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。抽象工厂模式:多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。 区别:工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
抽象工厂模式的优点:
1)封装性,每个产品的实现类不是高层模块要关心的,要关心的是什么?是接口,是抽象,它不关心对象是如何创建出来,这由谁负责呢?工厂类,只要知道工厂类是谁,我就能创建出一个需要的对象,省时省力,优秀设计就应该如此。
2)产品族内的约束为非公开状态。对调用工厂类的高层模块来说,它不需要知道这个约束,我就是要一辆汽车,自动挡的,你别在自动挡的车上给我装个离合器就好。具体你要怎么做,我并不关心。
抽象工厂模式的缺点:
抽象工厂模式的最大缺点就是产品族扩展非常困难,违反了开闭原则。
五、总结
参考: