《大话设计模式》将于11月底由清华大学出版社出版
《大话设计模式》第29章-OOTV杯超级模式大赛—模式总结(一)
《大话设计模式》第29章-OOTV杯超级模式大赛—模式总结(二)
《大话设计模式》第29章-OOTV杯超级模式大赛—模式总结(三)
(接上篇)
“欢迎回到第一届OOTV杯超级设计模式大赛现场,下面是第三组,也就是行为型模式一组的比赛,她们将穿VB.NET运动装出场。”
“首先出场的是13号选手,观察者小姐入场,它的口号是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。[DP]”
13号选手 观察者(Observer)
14号选手 模板方法(TemplateMethod)
“15号选手是命令小姐,它觉得应该将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;可以对请求排队或记录请求日志,以及支持可撤销的操作。[DP]”
15号选手 命令(Command)
“16号是状态小姐,她说允许一个对象在其内部状态改变时改变它的行为,让对象看起来似乎修改了它的类。[DP]”
16号选手 状态(State)
“本组最后一位,17号选手,职责链小姐,她一直认为使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。[DP]”
17号选手 职责链(Chain of Responsibility)
观众席中的ADO.NET和Hibernate又开始了讨论。
Hibernate :“VB.NET是你们.NET家族的品牌吧?”
ADO.NET:“是的,最早是BASIC,它是很古老的一个品牌,经过二十多年的发展,它已经成功地从以简单入门为标准转到了完全面向对象,真的很不容易,即简单易懂,又功能强大,所以它做出的运动装非常实用。”
Hibernate:“行为型模式的小姐们长得怎么都不太一样,风格差异也太大了。我不喜欢。”
ADO.NET:“我却觉得还不错,它们大多各有各的特长,比如这一组,应该还是有点看头,观察者、模板方法、命令都算是比较强的选手。”
Hibernate :“多半是观察者胜出了,因为她实在是到处接拍广告,做宣传,什么地方都能见到她的踪影,恨不得通知所有人,她是一设计模式。”
ADO.NET:“我猜也是她,人家本来就是以通知为主要魅力点的模式呀。咱们拭目以待吧。”《大话设计模式》
“下面有请评委提问。”主持人GOF说。
“请问观察者小姐,说说你对解除对象间的紧耦合关系的理解?”依赖倒转问道。
“我觉得对象间,尤其是具体对象间,相互知道的越少越好,这样发生改变时才不至于互相影响。对于我来说,目标和观察者不是紧密耦合的,它们可以属于一个系统中的不同抽象层次,目标所知道的仅仅是它有一系列的观察者,每个观察者实现Observer的简单接口,观察者属于哪一个具体类,目标是不知道的。”
“非常好,请问模板
模板方法说,“代码重复是编程中最常见、最糟糕的‘坏味道’,如果我们在一个以上的地方看到相同的程序结构,那么可以肯定,设法将它们合而为一,程序会变得更好[RIDEC]。但是完全相同的代码当然存在明显的重复,而微妙的重复会出现在表面不同但是本质相同的结构或处理步骤中[R2P],这使得我们一定要小心处理。继承的一个非常大的好处就是你能免费地从基类获取一些东西,当你继承一个类时,派生类马上就可以获得基类中所有的功能,你还可以在它的基础上任意增加新的功能。模板方法模式由一个抽象类组成,这个抽象类定义了需要覆盖的可能有不同实现的模板方法,每个从这个抽象类派生的具体类将为此模板实现新方法[DPE]。这样就使得,所有可重复的代码都提炼到抽象类中了,这就实现了代码的重用。”
“下面请问命令小姐,为什么要将请求发送者与具体实现者分离?这有什么好处?”单一职责问道。
“您的意思其实就是将调用操作的对象与知道如何实现该操作的对象解耦,而这就意味着我可以在这两者之间处理很多事,比如完全可以发送者发送完请求就完事了,具体怎么做是我的事,我可以在不同的时刻指定、排列和执行请求。再比如我可以在实施操作前将状态存储起来,以便支持取消/重做的操作。我还可以记录整个操作的日志,以便以后可以在系统出问题时查找原因或恢复重做。当然,这也就意味着我可以支持事务,要么所有的命令全部执行成功,要么恢复到什么也没执行的状态。总之,如果有类似的需求时,利用命令模式分离请求者与实现者,是最明智的选择。”
“OK,职责链小姐,提问命令小姐的问题同样提问给你,为什么要将请求发送者与具体实现者分离?这有什么好处?你如何回答。”
“我们时常会碰到这种情况,就是有多个对象可以处理一个请求,哪个对象处理该请求事先并不知道,要在运行时刻自动确定,此时,最好的办法就是让请求发送者与具体处理者分离,让客户在不明确指定接收者的情况下,提交一个请求,然后由所有能处理这请求的对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。”职责链答道,“比如我住在县城,生了怪病,我不知道什么级别的医院可以诊治,显然最简单的办法就是马上找附近的医院,让此医院来决定是否可以治疗,如果不能则医院会提供转院的建议,由县级转市级、由市级转省级、由省级转国家级,反正直到可以治疗为至。这就不需要请求发送者了解所有处理者才能处理问题了。”
“非常好,例子很形象,不过得怪病不是好事,健康才最重要。”开放封闭微笑道,“下面请问最后一位,状态小姐,条件分支的大量应用有何问题?如何正确看待它?”
状态答道:“如果条件分支语句没有涉及重要的商务逻辑或者不会随着时间的变化而变化,也不会有任何的可扩展性,换句话说,它几乎不会变化,此时条件分支是应该使用的。但是注意我这里用到了很多前提,这些前提往往都是不成立的,事实上不会变化的需求很少,不需要扩展的软件也很少,那么如果把这样的分支语句进行分解并封装成多个子类,利用多态来提高其可维护、可扩展的需要,是非常重要的。状态模式提供了一个更好的办法来组织与特定状态相关的代码,决定状态转移的逻辑不在单块的if或switch中,而是分布在各个状态子类之间,由于所有与状态相关的代码都存在于某个状态子类中,所以通过定义新的子类可以很容易地增加新的状态和转换。[DP]”《大话设计模式》
“下面有请六位评委写上你们认为表现最好的模式小姐。”GOF说道。
“喔,观察者3票、模板方法2票、命令1票,最终观察者小姐晋级。”GOF在等评委翻牌后宣布道。“恭喜你,观察者小姐,有什么要说的吗?”
观察者小姐平静地说:“感谢所有关心我、喜欢我和憎恨我的人。比赛中的环境不太干净,但我是干净地站起来的。”
“啊,你,你说憎恨?不干净?什么意思?”GOF非常意外。
“无可奉告。”观察者显然知道刚才那些话的影响,所以选择回避。
“哦,”GOF有些尴尬,“下面先进段广告,广告后我们进行第四组的比赛。”慌忙之中,GOF连让短信投票的宣传都忘记说了。
此时场下观众都议论纷纷。当然ADO.NET和Hibernate两位也不例外。
ADO.NET:“你说她被谁憎恨了?”
Hibernate :“那谁知道。不过一定是来参赛前,受到了一些阻挠,甚至于产生了很大的矛盾,因此才有了憎恨一说。其实憎恨也就罢了,‘不干净’一词力道可就重了。”
ADO.NET:“这有什么,只不过观察者她胆子大,说了出来。在娱乐圈、体育圈有潜规则,难道我们程序世界里就没有潜规则?”
Hibernate :“是呀,只要涉及到利益,就不可能没有交易。我再给你爆个料,MVC你听说过吗?”
ADO.NET:“知道呀,大名鼎鼎的MVC模式,就是Model/View/Controller,非常漂亮的姑娘。在电视上经常能看到它,好像谈模式、谈架构没有不谈到她的。”
Hibernate :“你可知道为何她没来参加这次超级模式大赛?”
ADO.NET:“咦,对哦,为什么她没来参加呢,要是她来,和这23个比,至少前三是一定可以进的。你不要告诉我,因为她被潜规则了?”
Hibernate :“我偷偷告诉你,你可别出去乱传。MVC是包括三类对象,Model是应用对象,View是它在屏幕上的表示,Controller定义用户界面对用户输入的响应方式。如果不使用MVC,则用户界面设计往往将这些对象混在一起,而MVC则将它们分离以提高灵活性和复用性[DP]。因此,有人甚至说,她是集观察者、组合、策略三个美女优点于一身的靓女。海洗和选拔赛时她都表现非常好的,但因为一次短信的事情,而她又在自己博客里写了《非得这样吗?》的文章,大大地得罪了主办方的一个大鳄。于是由于这件事,她就彻底把自己的前途给葬送了。后来博客的文章也被勒令删除。”
ADO.NET:“得罪谁了?短信什么内容?”
Hibernate:“我哪知道呀,反正她后来就退出比赛了。”
ADO.NET:“你这也叫爆料呀,什么都没说出来,根本就一个听风是雨没任何根据的小道消息。据我猜测,主要原因是这次是设计模式比赛,而MVC是多种模式的综合应用,应该算是一种架构模式,所以被排除在外。”
Hibernate:“不信就算了,不过你说的也有道理。”《大话设计模式》
(未完待续)
再次声明一下,本29章,可以代表本书的幽默风格,却不能代表本书的讲解技术的方式。正因为这一章的最与众不同,我本想让朋友们可以从全新的视角去看待23个设计模式,回顾一下它们的相同与不同。可惜是剑就有双刃,我忽略了有很多朋友是不了解《小菜编程成长记》的,以为本书全是这种娱乐化的书写,因此得出这样的文字不能得到收获结论。事实并非如此,否则出版社也不会出版本书,而只会让它上IT娱乐杂志了。在将此章结束后,我会帖出讲解设计模式的样章,希望您继续关注。