附加概念:
产品等级结构:不同品牌的同一类产品,如Haier电视机,TCL电视机都是电视机,因此属于同一个产品等级结构。
产品族:属于同一个品牌的所有产品,如Haier电视机,Haier冰箱等。
模式动机:工厂方法模式一般针对的是一个产品等级结构(如仅生产电视机),而抽象工厂模式针对的是多个产品等级结构(如不仅生产电视机,还生产空调)。
模式定义:一个具体工厂可以创建一个产品族的所有产品,又称为Kit模式。
模式结构图:
模式实例:
一个电器工厂负责生产电视机和空调,其中包括Haier系列和TCL系列,使用抽象模式设计如下:
1> 定义一个抽象工厂类EFactory,其中提供生产电视机和空调的接口;
2> 分别定义工厂子类HaierFactory和TCLFactory实现具体的生产电视机和空调的方法;
3> 定义一个电视机接口Television;
4> 定义具体品牌的电视机类HaierTelevision和TCLTelevision分别实现电视机接口Television;
5> 定义一个空调接口AirConditioner;
6> 定义具体品牌的空调类HaierConditioner和TCLConditioner分别实现电视机接口Conditioner;
其模式结构图如下:
模式代码:
bt_抽象工厂模式.h:
1 #ifndef AFP_H 2 #define AFP_H 3 4 #include <iostream> 5 6 /* **************************产品接口********************************** */ 7 class Television // 定义电视机产品接口 8 { 9 public: 10 virtual ~Television(); 11 virtual void play() = 0; 12 }; 13 Television::~Television(){ } 14 15 class AirConditioner // 定义空调产品接口 16 { 17 public: 18 virtual ~AirConditioner(); 19 virtual void changeTemperature() = 0; 20 }; 21 AirConditioner::~AirConditioner(){ } 22 23 /* **************************Haier产品类********************************** */ 24 class HaierTelevision : public Television // 具体的Haier电视机类 25 { 26 public: 27 virtual void play(); 28 }; 29 void HaierTelevision::play(){ } 30 31 class HaierAirConditioner : public AirConditioner // 具体的Haier空调类 32 { 33 public: 34 virtual void changeTemperature(); 35 }; 36 void HaierAirConditioner::changeTemperature(){ } 37 38 /* **************************TCL产品类********************************** */ 39 class TCLTelevision : public Television // 具体的TCL电视机类 40 { 41 public: 42 virtual void play(); 43 }; 44 void TCLTelevision::play(){ } 45 46 class TCLAirConditioner : public AirConditioner // 具体的TCL空调类 47 { 48 public: 49 virtual void changeTemperature(); 50 }; 51 void TCLAirConditioner::changeTemperature(){ } 52 53 54 55 /* **************************工厂接口************************************** */ 56 57 class EFactory // 定义抽象工厂 58 { 59 public: 60 virtual ~EFactory(); 61 virtual Television* produceTelevision() = 0; // 生产电视机的接口 62 virtual AirConditioner* produceAirConditioner() = 0; // 生产空调的接口 63 }; 64 EFactory::~EFactory(){ } 65 66 /* **************************Haier工厂类********************************** */ 67 class HaierFactory : public EFactory // 定义生产Haier产品系列的工厂 68 { 69 public: 70 virtual Television* produceTelevision(); // 生产Haier电视机 71 virtual AirConditioner* produceAirConditioner(); // 生产Haier空调 72 }; 73 Television* HaierFactory::produceTelevision() 74 { 75 std::cout << "生产了一台Haier电视机" << std::endl; 76 return new HaierTelevision; 77 } 78 AirConditioner* HaierFactory::produceAirConditioner() 79 { 80 std::cout << "生产了一台Haier空调" << std::endl; 81 return new HaierAirConditioner; 82 } 83 84 /* **************************TCL工厂类********************************** */ 85 class TCLFactory : public EFactory // 定义生产TCL产品系列的工厂 86 { 87 public: 88 virtual Television* produceTelevision(); // 生产TCL电视机 89 virtual AirConditioner* produceAirConditioner(); // 生产TCL空调 90 }; 91 Television* TCLFactory::produceTelevision() 92 { 93 std::cout << "生产了一台TCL电视机" << std::endl; 94 return new TCLTelevision; 95 } 96 AirConditioner* TCLFactory::produceAirConditioner() 97 { 98 std::cout << "生产了一台TCL空调" << std::endl; 99 return new TCLAirConditioner; 100 } 101 102 #endif // AFP_H
bt_抽象工厂模式.cpp:
1 #include <iostream> 2 #include "bt_抽象工厂模式.h" 3 4 using namespace std; 5 6 int main() 7 { 8 // 客户端生产电视机时只需和抽象工厂与抽象电视机交互即可 9 EFactory* factory; 10 factory = new HaierFactory; // Haier工厂 11 Television* tv; 12 AirConditioner* ac; 13 tv = factory->produceTelevision(); // 多态调用:生产Haier电视机 14 ac = factory->produceAirConditioner(); // 多态调用:生产Haier空调 15 16 factory = new TCLFactory; // TCL工厂 17 tv = factory->produceTelevision(); // 多态调用:生产TCL电视机 18 ac = factory->produceAirConditioner(); // 多态调用:生产TCL空调 19 20 delete factory; 21 delete tv; 22 delete ac; 23 24 return 0; 25 }
模式优缺点:
添加新的产品族(即一个新的品牌)比较容易,此时只需要定义新的工厂和产品类即可;但增加产品等级(即原有品牌的种类)比较麻烦,此时必须修改抽象工厂以添加新种类的生产接口,同时所有已有的产品族工厂也要修改,这就违背了“开闭原则”。该模式具体应用中一般适合对象的多种状态同时发生变化时,比如操作系统中的主题管理程序等。
比较:
抽象工厂模式针对的是多个产品等级,而工厂方法模式针对的是一个产品等级,抽象工厂模式经过退化后完全可以变为工厂方法模式,甚至是简单工厂模式。