首先啰嗦下创建迷宫所用的Room类。这个类并不直接保存Room四周的构造,而是通过MapSite* _sides[4]这个私有数组成员指向Room四周的构造。那么什么时候将四周构造直接放在Room中,什么时候通过指针访问,这两种方式各有神马优缺点?这是个问题[2015.10.07:你无法预先确定四周构造的具体类型,所以没办法将其直接放在Room中,只能使用基类指针]……不过这不是Abstract Fractory的重点,先放一边吧。
就“Factory”这个词的本义来说,上面这张图本身就够抽象的。让我们用更贴近“Factory”一词的汽车厂来作例子。
在遥远的北方大陆上有两家汽车厂,一家是BMW,一家是Benz。他们生产的汽车只有两个部件:方向盘和轮子(别问我这样的汽车怎么开)。于是我们的Abstract Factory有两个Virtual方法:CreateSteering,CreateWheel。自然,BMWFactory和BenzFactory各自造出的轮子和方向盘是有区别的。
另一方面,不管BMW的轮子还是Benz的轮子,都是圆的,能在地上滚动的;方向盘同样有其共同点。所以我们有AbstractSteering和AbstractWheel以及它们的派生类。
综上,“工厂”有“抽象工厂”和具体的“实际工厂”;
“工厂产品”有“抽象产品”和具体的“实际产品”。
“工厂类”和其生产产品的“产品类”是分开的,但各个工厂生产的产品种类是一样的,这样才能在Factory Class和Product Class之间建立对应关系。
下面是代码:
1 // 编译环境:VS2008 2 // AbstractFactory.cpp : 定义控制台应用程序的入口点。 3 // 4 5 #include "stdafx.h" 6 #include7 8 using namespace std; 9 10 class AbstractWheel 11 { 12 public: 13 14 }; 15 16 class BenzWheel : public AbstractWheel 17 { 18 public: 19 BenzWheel() 20 { 21 cout << "I am BenzWheel" << endl; 22 } 23 }; 24 25 class BMWWheel : public AbstractWheel 26 { 27 public: 28 BMWWheel() 29 { 30 cout << "I am BMWWheel" << endl; 31 } 32 }; 33 34 class AbstractSteering 35 { 36 public: 37 38 }; 39 40 class BenzSteering 41 { 42 public: 43 BenzSteering() 44 { 45 cout << "I am BenzSteering" << endl; 46 } 47 }; 48 49 class BMWSteering 50 { 51 public: 52 BMWSteering() 53 { 54 cout << "I am BMWSteering" << endl; 55 } 56 }; 57 58 class AbstractFactory 59 { 60 public: 61 virtual void CreateWheel(); // No implement in virtual base class 62 virtual void CreateSteering(); // No implement in virtual base class 63 }; 64 65 class BenzFactory 66 { 67 public: 68 virtual void CreateWheel() 69 { 70 new BenzWheel(); 71 } 72 virtual void CreateSteering() 73 { 74 new BenzSteering(); 75 } 76 }; 77 78 class BMWFactory 79 { 80 public: 81 virtual void CreateWheel() 82 { 83 new BMWWheel(); 84 } 85 virtual void CreateSteering() 86 { 87 new BMWSteering(); 88 } 89 }; 90 91 void CreateCar(AbstractFactory& factory) 92 { 93 factory.CreateSteering(); 94 factory.CreateWheel(); 95 } 96 97 int _tmain(int argc, _TCHAR* argv[]) 98 { 99 // I want a BMW car100 BMWFactory factory;101 CreateCar((AbstractFactory&)factory);102 // I want a Benz car103 //BenzFactory factory;104 //CreateCar((AbstractFactory&)factory);105 return 0;106 }
如果你想要一辆Benz car,将main()中的注释代码放开就可以了。
顺便说一下,上面代码中,CreateCar并不是Factory类的成员函数;这貌似不符合现实世界汽车厂的一贯做法。不过我们的代码例子主要为了演示Abstract Factory模式,而这种模式主要关心的是“产品部件生产”的抽象,而不关心“产品组装”的抽象,所以代码和现实的这点区别就忽略吧。或者想一想书中不同风格窗口的那个例子:不同风格窗口的组装是应用程序的事情,而不是Widget类库的事情。