[设计模式之禅读书笔记]008_23种设计模式二:工厂方法模式
序言
《设计模式之禅》看到第78页了,继续坚持啊!作为一个创建型的设计模式,工厂方法模式被使用到的频率相当高,因此,这个模式的学习那是相当有价值的。那么,这个模式的定义是怎样的呢?这个模式的实现是怎样的呢?这个模式的作用是怎样的呢?笔者将尽一切可能为读者解释清楚,当然,如果没有解释清楚的,可以一起讨论。这样的学习才有互动性,才能不断进步嘛!元芳,你怎么看?
正文
1. 你是怎么创建对象的?(最蠢的方法)
1 // 第一种 2 MyObject mo; 3 4 // 第二种 5 MyObject *mo = new MyObject();
靠,躺着也中枪!是的,我就是这么创建对象的啊!用什么创建什么呗,有什么问题吗?太蠢了。是的,从一个软件设计师的角度来看,各种丑陋,就跟山寨平板和ipad的对比一样。其实对于我们这些小猿来说,这样的写法最痛苦的是什么?没有智能提示啊!我要记住那么多个类的名字啊!那要怎么才能有智能提示呢?
2. 带智能提示的创建对象(简单工厂模式)
1 class IObject{ // 基类 2 }; 3 class MyObject:public IObject{ // 具体实现类 4 }; 5 class MyFactory{ //工厂类 6 public: 7 static IObject* createObject(const string& name){ 8 if(name == "MyObject"){ 9 return new MyObject(); 10 }else if(name == "YourObject"){ 11 ... 12 }else if(name == "HisObject"){ 13 ... 14 } 15 } 16 };
简单吧,用一个MyFactory来封装我们的创建工作就可以了,这样我只需要记住这个工厂——MyFactory的名字就可以了,这样我就可以用MyFactory::来得到智能提示的创建方法了。聪明的你肯定想到了另一个方法,是的,还有一个方法,我们把createObject方法拆开,就可以获取更好的智能提示了,代码如下:
1 class MyFactory{ 2 public: 3 static IObject* createMyObject(){ // 创建MyObject,不用记住字符串了 4 return new MyObject(); 5 } 6 static IObject* createYourObject(){ // 创建YourObject,不用记住字符串了 7 return new YourObject(); 8 } 9 ... 10 };
这样也可以的,看起来很给力的样子啊!如果我告诉你,你已经掌握了一种设计模式了,你信么?哈哈,恭喜你,你真的学会了一种设计模式了——简单工厂模式。怎样,名副其实的简单吧!可是我们的简单工厂模式有一个问题!
如果我们有了一个新的类HerObject,怎么办?简单的很,在MyFactory里面追加一个else if判断就可以了,不就加个字符串的事么。对后面的实现来说,不就是加个方法的事的么。屁大点事啊!可是,可是,可是,我们违背了设计模式六大原则的开闭原则(OCP)了,还记得吗?我们追加类的时候,修改了既有类,这怎么办?下面我们来改进一下这个简单工厂。
3. 改进简单工厂模式(工厂方法模式)
修改简单工厂模式的目的,就是使得我们新追加对一个新产物生产的工厂时,不会导致原有的代码被更改,看下面的代码:
1 class IObject{ 2 }; 3 4 class MyObject:public IObject{ 5 }; 6 7 ... 8 9 class IObjectFactory{ 10 public: 11 virtual IObject* createObject(){ 12 } 13 }; 14 class MyObjectFactory:public IObjectFactory{ // MyObject工厂 15 public: 16 IObject* createObject(){ 17 return new MyObject(); 18 } 19 }; 20 21 class YourObjectFactory:public IObjectFactory{ // YourObject工厂 22 public: 23 IObject* createObject(){ 24 return new YourObject(); 25 } 26 }; 27 28 int main(){ 29 IObjectFactory* factory = new MyObjectFactory(); // 新建工厂类 30 IObject* myObject = factory->createObject(); // 创建MyObject对象 31 }
看到好处没?如果我要追加个HisObject类,并且要添加一个生产HisObject的工厂,我只需要追加一个HisObjectFactory类即可,不会对原有的代码造成破坏。这就是我们的工厂方法模式。
4. 回首看一哈子(理论UML图)
最后,我们总结一下,上面的代码中我们分别实现了两种设计模式——简单工厂模式和工厂方法模式,当然,这两种模式我都没有用上C++的高级语言特性,比如template,不过我们的目的已经达到了,知道了工厂方法模式和简单工厂模式了。下面是两种模式的UML图:
简单工厂模式:
工厂方法模式:
总结
作为创建型的设计模式,工厂方法模式和简单工厂模式的使用频率是非常高的,掌握这两种设计模式对于我们设计自己的软件系统有很大的好处。不过这两种设计模式也有缺点,当然,缺点是出现在某些极端条件下的。对于我们的软件系统,要选择最适用的模式,就是说没有最好的设计模式,只有最合适的设计模式。