《大话设计模式》之--第8章 雷锋依然在人间----工厂方法模式

8 雷锋依然在人间----工厂方法模式

8.1再现活雷锋

小菜来找大鸟,说:“今天咱们见到活雷锋了。”java

“哦,”大鸟感兴趣道,“如今已经不多提这我的名了,说说看。”学习

“咱们班有个同窗叫薛磊风,昨天,他出了车祸,被车撞断了腿,医生说没大碍,能够恢复。”小菜说,“四年来,他作人很低调,只据说他时常去勤工俭学,周末通常就看不到他,别的也没感受到什么。”spa

“他不太走运,不过所谓‘常在路上走,哪有不碰车。’被车撞也是没办法的。”设计

“是呀,咱们今天白天去医院看望他,却听到了一个很是感人的故事,应该说,像是在电视里才能看到的真人真事。”code

“他作了感人的好事了!orm

“你怎么知道,哦,我告诉你见到活雷锋的。你别打岔。”小菜不满地说,“是这样的,他这几年,都一直在帮助一个孤寡老人,每周都去老人家里,为老人洗衣扫地、买米买油,三年多,一直这样,由于他家住在广西很偏远的地方,到了南宁还要再坐几天的汽车,因此他四年来没有回过老家,也正由于此,他对这位老人家的帮助从没有中止过。”xml

“但是如今出了意外,他住进医院,不能帮助他人了。”大鸟仍是打岔道,“这种事你骗谁呀,这么多孤寡老人,他为何只帮助这一位?对象

“你再打岔我就不说了,你不信也听听,接受一下再教育,我今天是受教育了。”小菜接着说。“他在大一的时候,从收音机里听到说,有位孤老早年丧妻,而惟一拉扯大的儿子在八十年代中越战争时牺牲了,而他正是从小生活在离战争不远的边防小镇,目击过战争的残酷和解放军的无私奉献。因此他一听到这个消息就主动去为老人提供帮助。老人身体很差,尽管有些社会的救济,但在生活上仍是不太方便,因而他帮助老人就成了每周末的功课。”继承

“哦,奉献精神代代传呀。”接口

“如今他住院了,至少近几个月都没办法去老人家,因此他委托咱们去帮他继续作这件好事,此时咱们你们才知道,雷锋原来就在咱们身边。”

“不容易,在21世纪,我还觉得这样的人愈来愈少了呢,原来乐于助人的事迹仍是比比皆是。”

“明天我和几名同窗就去老人家。不过老人不认识咱们,薛磊风也交待咱们不要提任何人的名字,就像他同样说是学雷锋作好事就好了。”

“作了好事不留名,坚持不懈三年多,真让人佩服呀,受教育了。”大鸟感慨地说。

8.2简单工厂模式实现

“好了,我来是为了请教你一个问题,这几天一直在研究工厂方法模式,但仍是不太理解它和简单工厂的区别,感受还不如简单工厂方便,为何要用这个模式,到底这个模式的精翻在哪里?”

“哈,你刚才讲的故事不就是最好的工厂方法的样例吗?”

“薛磊风的事?怎么讲?”

“那你先把简单工厂模式和工厂方法模式的典型实现说给我听听。”

“哦,简单工厂模式实现是这样的。”

“首先简单工厂模式,若以我写的计算器为例,结构图以下。”

 

8.3工厂方法模式实现

“那若是换成工厂方法模式来写这个计算器,你能写吗?”

“固然能够,就是由于我写出来了,才感受好像工厂方法没什么好处!我写给你看。”

“计算器的工厂方法模式实现的结构图是这样的。”

“对啊,写的很好。”大鸟说,“工厂方法模式就是这样写的,你有什么问题?”

8.4简单工厂VS工厂方法

“怪就怪在这里啊,之前咱们不是说过嘛,若是我如今须要增长其余运算,好比求M数的N次方,或者求M数的N次方根,这些功能的增长,在简单工厂里,我是先去加‘求M数的N次方’功能类,而后去更改工厂方法,当中加Caseif语句来作判断,如今用了工厂方法,加功能类没问题,再加相关的工厂类,这也没问题,但要我再去更改客户端,这不等于不但没有简化难度,反而增长了不少类和方法,把复杂性增长了嘛?为何要这样?”

“问的好,这其实就是工厂方法模式和简单工厂的区别所在。简单工厂模式的最大优势在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来讲,去除了与具体产品的依赖。就像你的计算器,让客户端不用管该用哪一个类的实例,只须要把‘+’给工厂,工厂自动就给出了相应的实例,客户端只要去作运算就能够了,不一样的实例会实现不一样的运算。但问题也就在这里,如你所说,若是要加一个‘求M数的N次方’的功能,咱们是必定须要给运算工厂类的方法里加Caseif的分支条件的,修改原有的类?这可不是好办法,这就等于说,咱们不但对扩展开放了,对修改也开放了,这样就违背了什么原则?”

“哦,是的,违背的是开放-封闭原则。”

“对,因而工厂方法就来了。”

工厂方法模式(Factory Method),定义一个用于建立对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。工厂方法模式结构图。

“咱们讲过,既然这个工厂类与分支耦合,那么我就对它下手,根据依赖倒转原则,咱们把工厂类抽象出一个接口,这个接口只有一个方法,就是建立抽象产品的工厂方法。而后,全部的要生产具体类的工厂,就去实现这个接口,这样,一个简单工厂模式的工厂类,变成一个工厂抽象接口和多个具体生成对象的工厂,因而咱们要增长‘求M数的N次方’的功能时,就不须要更改原有的工厂类了,只须要增长此功能的运算类和相应的工厂类就能够了。”

“这样整个工厂和产品体系其实都没有修改的变化,而只是扩展的变化,这就彻底符合了开放-封闭原则的精神。”

“哦,工厂方法从这个角度来说,的确要比简单工厂模式来得强。”

“其实你仔细观察就会发现,工厂方法模式实现时,客户端须要决定实例化哪个工厂来实现运算类,选择判断的问题仍是存在的,也就是说,工厂方法把简单工厂内部的逻辑判断移到了客户端代码来进行。你想要加功能,原本是改工厂类的,而如今要改客户端了!”

“这也是我困惑的地方。”

8.4雷锋工厂

“这个咱们过会再讲,以你刚才讲的故事来讲吧,雷锋是人人皆知的作好人好事的模范,而班级的这位薛磊风同窗以学习雷锋的名义作好事,而大家如今须要去代替他作好事,这其实就是典型的工厂方法模式应用了。”

“哦,你说来听听。”

“首先,薛磊风做为一个大学生,以学雷锋作好事的名义去帮助老人作事,这里如何设计?”

“个人想法是这样的:雷锋类拥扫地、洗衣、买米等方法。”

“小菜写的不错,如今假设大家有三我的要去代替他作这些事,那应该怎样写?”

“那就应该实例化三个学雷锋的大学生对象了。”

“大家都是要毕业的,而帮助老人倒是长期工做,因此‘社区志愿者’更合适,此时这样的写法就很是的不合适了,由于咱们须要更改多个实例化的地方。”

“是啊,其实老人不须要知道是谁来作好事,他只须要知道是学雷锋的人来帮忙就能够了。因此还须要增长一个继承‘雷锋’类的‘社区志愿者’类。”

“好,此时你就发现了,你须要在任何实例化的时候写出这个工厂的代码。这里有重复,也就有了坏味道。你再用工厂方法模式写一遍。”

 

“我明白了,尽管若是要换成‘社区志愿者’也仍是要修改代码,可是只须要修改一处就能够了,这是最佳的作法。”

“最佳作法?NOPNOPNOP,这不是最好的,不过应该算是比较好的了。你如今明白何时用简单工厂模式,何时用工厂方法模式了没?”

“我感受啊,工厂方法模式克服了简单工厂违背开放-封闭原则的缺点,又保持了封闭对象建立过程的优势。”

“说的好,它们都是集中封闭了对象的建立,使得要更换对象时,不须要作大的改动就能够实现,下降客户程序与产品对象的耦合。工厂方法模式是简单工厂模式的进一步抽象和推广。因为使用了多态性,工厂方法模式保持了简单工厂模式的优势,并且克服了它的缺点。但缺点是因为每加一个产品,就须要加一个产品工厂的类,增长了额外的开发量。”

“你说这不是最佳作法?难道说还有更好的?还有就是这样仍是没有避免修改客户端的代码啊!”

“哈,以前我就提到过,利用‘反射’能够解决避免分支判断的问题。不过今天仍是不急,等之后再谈。你明天不是还要去看望老人家吗?洗洗睡吧,这年头,活雷锋太少了,大家班那个薛磊风,实在是太不容易了,要是有雷锋工厂该有多好啊。”

“雷锋工厂!雷锋工厂!是啊,若是每一个人都有雷锋精神,这世界该有多么美好啊”小菜念叨着,不觉中唱到:“学习雷锋,好榜样,忠于革命忠于党,爱憎分明不忘本,立场坚决斗志强