程序设计模式 —— 抽象工厂模式
前言
工厂?意思是创建变量的厂子?要这个干什么?为什么不直接new new new!!
定义:为创建一组相关或相互依赖的对象提供一个接口,而无需指定他们的具体类。
但是,从现在开始,请不要再使用new。
“What?不使用new?你怎么写C++程序,怎么写Java程序?”
我应该如何阅读?
本文将使用优雅的文字风格来告诉你什么是工厂模式。
注意:
1.在阅读本文之前请保证你已经掌控了 面对对象的思想与 多态的基本概念,否则将难以理解。
2.本文实现将用C++实现,你不一定必须学会C++,这些代码都有非常丰富的注释和简单的语法。
3.请不要跳着看,除非你已经学会。
什么是工厂模式?
准确的说,工厂有两个,一个是简单工厂,一个是抽象工厂。
在《HeadFrist 设计模式》 一书当中说道:”简单工厂其实不是一个设计模式,更像是一种编程习惯,有些开发人员的确误以为是工厂模式。“
简单工厂是什么?
简单工厂顾名思义,十分简单,请看下面少量代码
注意:Entity 是一个抽象类,HelicopterA 是直升机A类型继承Entity ,HelicopterB 是直升机B类型继承Entity,暂且无需管具体代码,下面代码不影响。
1 /*这是一个直升机工厂*/ 2 class HelicopterFactory 3 { 4 public: 5 virtual Entity* create(const char* name) 6 { 7 Entity *p = NULL; 8 if(name == "A"){ 9 cout << "[Factory] create: HelicopterA" << endl; 10 p = new HelicopterA(); 11 } 12 if(name == "B"){ 13 cout << "[Factory] create: HelicopterB" << endl; 14 p = new HelicopterB(); 15 } 16 /** 17 if(name == "B"){ 18 cout << "[Factory] create: HelicopterB" << endl; 19 p = new HelicopterB(); //更多更多的 产品 20 //这样,你的创建都集中在了一个类中间。当然了工厂模式不止这点点。 21 } 22 */ 23 return p; 24 }; 25 };
注意:如果你不会 C++,也没有关系,”Virtual” 关键字你可以无视,可以用Java的思想去看待代码
然后我们写主函数:
1 HelicopterFactory hFactory = new HelicopterFactory(); 2 Entity *heli = hFactory->create("A"); 3 /*报告老板,我已经造好了直升机!*/ 4 heli->exec(); 5 heli = hFactory->create("B"); 6 heli = hFactory->create("B"); //我们这样就可以随意创建 7 heli = hFactory->create("B"); 8 heli = hFactory->create("B"); 9 heli = hFactory->create("B"); 10 /*报告老板,我已经造好了直升机!*/ 11 heli->exec();//
至此,我们的简单工厂就是这样,看起来就是将创建的代码放到了一个专门的类里面了。
就这么简单?是的,简单工厂就这么简单。
但是如果我们要创建航天飞机呢?这个时候我们就要用到抽象工厂了。事实上也十分容易。设计模式其实都是很简单的,之所以出现了设计模式就是为了解决问题。
抽象工厂又是什么?
实现框架图:务必仔细看看
说白了就是我们可以创建各种各样的工厂,但是在实际使用的时候,我们是不需要知道究竟是哪个工厂。
我们来看看Entity类
1 /*实体类 基类抽象类*/ 2 class Entity 3 { 4 public: 5 Entity() 6 { 7 8 }; 9 virtual ~Entity() 10 { 11 12 }; 13 virtual void exec()=0; //启动 交给子类实现 14 };
然后我们来实现 直升机 和 航天飞机 类
1 /*直升机类 类型A*/ 2 class HelicopterA : public Entity 3 { 4 public: 5 virtual void exec() 6 { 7 cout << "HelicopterA Fly!" << endl; 8 } 9 }; 10 /*直升机类 类型B*/ 11 class HelicopterB : public Entity 12 { 13 public: 14 virtual void exec() 15 { 16 cout << "HelicopterB Fly!" << endl; 17 } 18 }; 19 20 /*航天飞机 类型A*/ 21 class ShuttleA : public Entity 22 { 23 public: 24 virtual void exec() 25 { 26 cout << "ShuttleA Fly!" << endl; 27 } 28 }; 29 30 /*航天飞机 类型B*/ 31 class ShuttleB : public Entity 32 { 33 public: 34 virtual void exec() 35 { 36 cout << "ShuttleB Fly!" << endl; 37 } 38 };
好的,到现在为止我们已经有了 “产品”,现在我们应该来制作 “工厂”了:
首先实现抽象工厂类:
1 /*抽象工厂类*/ 2 class AbstractFactory 3 { 4 public: 5 virtual ~AbstractFactory() 6 { 7 8 }; 9 virtual Entity* create(const char*)=0;//交给子类去实现,这是创建实例的方法 10 };
现在我们来写两个具体工厂,直升机工厂和航天飞机工厂(你总不可能认为直升机工厂能制造出 航天飞机吧?)
1 /*这是一个直升机工厂*/ 2 class HelicopterFactory : public AbstractFactory 3 { 4 public: 5 HelicopterFactory() 6 { 7 cout << "--Create HelicopterFactory--" << endl; 8 }; 9 virtual ~HelicopterFactory() 10 { 11 12 }; 13 virtual Entity* create(const char* name) 14 { 15 Entity *p = NULL; 16 if(name == "A"){ //根据你要的名字来进行相应的new 17 cout << "[Factory] create: HelicopterA" << endl; 18 p = new HelicopterA(); 19 } 20 if(name == "B"){ 21 cout << "[Factory] create: HelicopterB" << endl; 22 p = new HelicopterB(); //根据你要的名字来进行相应的new 23 } 24 /** 25 if(name == "B"){ 26 cout << "[Factory] create: HelicopterB" << endl; 27 p = new HelicopterB(); //更多更多的 产品 28 //这样,你的创建都集中在了一个类中间。当然了工厂模式不止这点点。 29 } 30 */ 31 return p; 32 }; 33 }; 34 35 /*这是一个航天飞机工厂*/ 36 class ShuttleFactory : public AbstractFactory 37 { 38 public: 39 ShuttleFactory() 40 { 41 cout << "--Create ShuttleFactory--" << endl; 42 }; 43 virtual ~ShuttleFactory() 44 { 45 46 }; 47 virtual Entity* create(const char* name) 48 { 49 Entity *p = NULL; 50 if(name == "A"){//根据你要的名字来进行相应的new 51 cout << "[Factory] create: ShuttleA" << endl; 52 p = new ShuttleA(); 53 } 54 if(name == "B"){//根据你要的名字来进行相应的new 55 cout << "[Factory] create: ShuttleB" << endl; 56 p = new ShuttleB(); 57 } 58 /*更多 种类的航天飞机*/ 59 return p; 60 }; 61 };
厂子应该要开工了!
现在我们写主函数:
“很好,你现在是 Pattern Art Online (R) 公司的员工,现在老板希望你为他在 Pattern Art Online 世界里面开个厂子,你十分肯定的说对于OO(object orient)程序员来说,这尼玛太简单了。。 ”
“你的大脑中已经出现了老板表扬的场景....”
1 int main(int argc, char const *argv[]) 2 { 3 /*好的,我们现在来创建一个抽象工厂*/ 4 AbstractFactory *hFactory; 5 /*具体化成 直升机工厂*/ 6 hFactory = new HelicopterFactory(); 7 /*然而我们并不需要管到底是什么,反正create就对了!*/ 8 Entity *heli = hFactory->create("A"); 9 /*报告老板,我已经造好了直升机!*/ 10 heli->exec(); 11 /*并且已经 可以启动了*/ 12 /*什么?客户换需求了?要求航天飞机?好吧*/ 13 /*幸好我用的是抽象的工厂,反正代码还是那样,只是需要换一个...*/ 14 delete hFactory; //嘿!别忘记释放原先了, 15 //这可不是Java语言,老实说我挺喜欢手动释放的,让我感觉什么都是我操作。好吧不扯这些了 16 hFactory = new ShuttleFactory(); 17 /*制造*/ 18 Entity *ent = hFactory->create("B"); 19 ent->exec();//运行 20 Entity *www = hFactory->create("A");//制造 21 www->exec();//运行 22 23 /*恭喜你,我相信你已经学会了 抽象工厂模式*/ 24 cin.get();//无视。由于我没有使用IDE,所以cin.get只是用于 暂停控制台 25 return 0; 26 }
“很好,这一次,你总算没有任何作弊行为和差错完成了。等等,为什么要加个总算?(具体故事情节在其他设计模式文章中)”
这个例子不是很好的体现了 抽象工厂的优势。但是主要是要你学习。
说明一下:
下面的话比较重要,建议仔细看看(别不承认,我保证你一定跳着在看)
我们声明的
1 AbstractFactory *hFactory;
是一个抽象工厂,它可以被其他子类/其他函数 赋值任何类型的工厂,但是我们只需要使用 create 成员函数 就可以直接创建,根本不需要管到底是什么工厂,因为对于我们来说是抽象的。
而且不知道你有没有发现,我们返回的也是 Entity 抽象类 这表示我们的主函数也不需要知道到底是 直升机 还是 航天飞机 ,反正调用 exec 成员函数 就对了。
整个就是抽象,根本不知道处理的究竟是什么,但是又很好的支持所有。
"其实我个人认为,也许有很多人也这么认为,程序员的主要解决问题的途径就是将问题抽象,抽象抽象再抽象。然后我们便可以适应问题。"
就这样结束了?
“你获得了老板的表扬,你的队友也敬佩你的才能,听说下个月你的工资又要涨( ̄︶ ̄)↗了”
“最重要的是,你的队友答应你加入 Pattern Art Online (AR)空战游戏的《Fly!Fly!Fly!》战队了,而且他们原谅了你之前的坠机失误。(这件事情发生在: 《设计模式——状态模式》)”
至此,我相信你已经会了这个模式。
什么?你告诉我你没完全懂?这个时候其实你应该配合代码和框架图组合来看,你一定会明白的。复习复习。
最后
但是要注意的一点,不是说有了这个模式,就必须要加进去使用,程序会更棒。
设计模式要与你的程序相互和谐,不能写个 “HelloWorld” 程序都用到了设计模式。
总的一句话,设计模式不是规则,而是你随时可以改变的模式。这也是很多设计模式书籍强调的一点。
不论对你是否有帮助,还是谢谢您的耐心查看。如有错误之处,还望指教。