《大话设计模式》第29章-OOTV杯超级模式大赛—模式总结(三)

《大话设计模式》将于11月底由清华大学出版社出版
《大话设计模式》第29章-OOTV杯超级模式大赛—模式总结(一)
《大话设计模式》第29章-OOTV杯超级模式大赛—模式总结(二)
(接上篇)

 

29.5  结构型模式比赛

此时的后台,第二组选手正在做着准备,电视台的记者抓紧时间,对适配器小姐做了一个小小的专访。

适配器小姐,您入选的结构型模式组被称为死亡之组,这一点您怎么看?”

“我觉得,所谓死亡之组,意思是有多个可能得冠军的选手不幸被分在了一组,造成有实力的选手会在小组赛中提前被淘汰,但那是针对体育比赛,我们这种选秀活动,选手只要充分表现了自己,就是成功,最终结果往往是多赢的局面。所以我不担心。”

“您觉得您有可能成为冠军吗?”

“不想当冠军的模式不是好模式。我来了,当然就是要努力争取第一。”

“您是否有与众不同的杀手锏来获得胜利?”

“我有杀手锏?”适配器小姐笑着摇摇头,“努力争取胜利就可以了。不好意思,我得准备去了,再见。”

适配器离开后,记者小声地对摄像师说,“你把最后一句擦掉。然后我们再录。”接着这记者拿着话筒对着摄像机,正式地说道:“观众朋友,适配器小姐说,她有成功致胜的杀手锏,但她却并没有提及内容,最终是什么让我们拭目以待。OOTV记者赵谣前方为您报道。”

“欢迎回到第一届OOTV杯超级设计模式大赛现场,下面是第二组,也就是结构型模式组的比赛,她们将穿C#休闲装出场。”

6号选手,适配器小姐,她的口号是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作[DP]《大话设计模式》

6号选手 适配器(Adapter

 

7号选手叫桥接桥接小姐提倡的是将抽象部分与它的实现部分分离,使它们都可以独立地变化[DP]

7号选手 桥接(Bridge

 

8号选手向我们走来,组合小姐,一个非常美丽的姑娘,她的口号是将对象组合成树形结构以表示‘部分-整体’的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性[DP]

8号选手 组合(Composite

 

9号选手,装饰小姐,她的意图非常简单,就是动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更加灵活[DP]。的确,她把自己装饰得非常漂亮。”

9号选手 装饰(Decorator

 

10号选手出现了,外观小姐,她的形象如她的名字一样的棒,她说为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用[DP]

10号选手 外观(Facade

 

11号选手是小姐,她的参赛宣言为运用共享技术有效地支持大量细粒度的对象[DP]

11号选手 享元(Flyweight

 

“本组了最后一位,12号选手,代理小姐向我们走来,她声称为其他对象提供一种代理以控制对这个对象的访问[DP]

12号选手 代理(Ptoxy

 

观众席中的ADO.NETHibernate又开始了讨论。

Hibernate:“C#休闲装我不喜欢,还是Java正装漂亮。”

ADO.NET:“哈,你这么正儿八经的人,当然是不喜欢休闲装,你兄弟NHibernate一定喜欢得不得了,我也是喜欢休闲装的。”

Hibernate :“这一组够强,没有太弱的,你感觉谁最有机会?”

ADO.NET:“不好说,都很漂亮的,各自有各自的特点,你认为呢?”

Hibernate :“我喜欢桥接,太漂亮了,那种解耦的方式,用聚合来代替继承,实在是非常巧妙。”

ADO.NET:“是的,桥接很漂亮,不过装饰也非常美丽。由于善于打扮,所以她可以很好地展示其魅力。”

Hibernate :“说得也是,装饰好歹也是靠化妆自己展示好看,而代理那个小妮子,听说她甚至有可能就不是自己来参加比赛,而是找了一替身。”

ADO.NET:“啊,不会吧,这种谣传你也会信呀,找人替身,那出了名算谁的?”

Hibernate :“当然还是她自己,大牌明星都这样的,找了替身做了很多,最后可能连替身名字都不让人家知道。”

ADO.NET:“代理要是大牌就不用来参加比赛了,出名前一切还是只有靠自己的。说心里话,我最喜欢的是适配器小姐。”

Hibernate:“哦,为什么喜欢她?她好像并不算漂亮。”

ADO.NET:“因为她对我的帮助最大,我在访问不同的数据库,如SQL ServerOracle或者DB2等时,需要将数据结构和数据都转化成XML格式给DataSetDataAdapter就是适配器,没有她的帮助,我的DataSet就发挥不了作用,真的很感激她。”

Hibernate:“哈,原来是恩人呀,打小认识的?青梅竹马?哈,好像就你认识她一样,我也和她是老相好哦。”

ADO.NET:“你就吹吧你,之前也听你说你和抽象工厂是相好,现在又和适配器相好,你的相好真够多的。”

Hibernate:“不信拉倒。我们不如来打赌吧,我赌10块钱,桥接会赢。”

ADO.NET:“瞧你那小气样,我赌100元,适配器会赢。”

Hibernate:“100100WhoWho呀。”《大话设计模式》

“下面有请评委提问。”主持人GOF说。

“请问适配器小姐,刚才记者提到你有成功的杀手锏,那是什么呢?”开放封闭先生问道。

“杀手锏?”适配器心里一咯噔,心想,“那记者太不道义了,我明明没有回答她的问题,怎么就断章取义地说我有杀手锏呢?造谣呀。”犹豫了一下,她说道,“我所谓的杀手锏是说,面向对象的精神就是更好地应对需求的变化,而现实中往往会有下面这些情况,想使用一个已经存在的类,而它的接口不符合要求,或者希望创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作。正如开放封闭先生您所倡导地对修改关闭,对扩展开放的原则,我可以做到让这些接口不同的类通过适配后,协同工作[DP]

开放封闭不住地点头。

桥接小姐,面对变化,你是如何做的?”合成聚合复用问道。

桥接答道:“继承是好的东西,但往往会过度地使用,继承会导致类的结构过于复杂,关系太多,难以维护,而更糟糕的是扩展性非常差。而仔细研究如果能发现继承体系中,有两个甚至多个方向的变化,那么就解耦这些不同方向的变化,通过对象组合的方式,把两个角色之间的继承关系改为了组合的关系,从而使这两者可以应对各自独立的变化,事实上也就是合成聚合复用女士所提倡的原则,总之,面对变化,我主张‘找出变化并封装之’。[DPE]

“这个问题也同样提问给装饰小姐,面对变化,你如何做?”合成聚合复用接着问装饰

装饰显然对此问题很有信心,答道:“面对变化,如果采用生成子类的方法进行扩充,为支持每一种扩展的组合,会产生大量的子类,使得子类数目呈爆炸性增长。这也是刚才桥接小姐所提到的继承所带来的灾难,而事实上,这些子类多半只是为某个对象增加一些职责,此时通过装饰的方式,可以更加灵活、以动态、透明的方式给单个对象添加职责,并在不需要时,撤销相应的职责。[DP]

组合小姐,我们通过你的材料,了解到你最擅长于表示对象的部分与整体的层次结构。那么请问,你是如何做到这一点的?”里氏代换问道。

组合答道:“我是希望用户忽略组合对象与单个对象的不同,用户将可以统一地使用组合结构中的所有对象。”组合回答道,“用户使用组合类接口与组合结构中的对象进行交互,如果接收者是一个叶节点,则直接处理请求,如果接收者是组合对象,通常将请求发送给它的子部件,并在转发请求之前或之后可能执行一些辅助操作。组合模式的效果是客户可以一致地使用组合结构和单个对象任何用到基本对象的地方都可以使用组合对象[DP]

一直没有提过问题的米特先生,突然接过话筒,对着外观小姐问了个问题,“请问外观小姐信息的隐藏促进了软件的复用[J&DP],你怎么理解这句话?”

外观小姐有些紧张,停顿了一会,然后缓缓答道,“类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及如果两个类不必彼此直接通信,那么就不要让这两个类发生直接的相互作用。如果实在需要调用,可以通过第三者来转发调用。[J&DP]

“那你又是如何去贯彻这一原则呢?”迪米特继续问道。

“我觉得应该让一个软件中的子系统间的通信和相互依赖关系达到最小,而具体办法就是引入一个外观对象,它为子系统间提供了一个单一而简单的屏障[DP]。通常企业软件的三层或N层架构,层与层之间地分离其实就是外观模式的体现。”外观小姐说话很慢,但显然准备过,并没说错什么。迪米特满意地点了点头。

小姐,请问你如何看待很多对象使得内存开销过大的问题?”单一职责问道。

对象使得内存占用过多,而且如果都是大量重复的对象,那就是资源的极大浪费[DP],会使得机器性能减慢,这个显然是不行的。”享元说,“面向对象技术有时会因简单化的设计而代价极大。比如文档处理软件,当中的字符都可以是对象,而如果让文档中的每一个字符都是一个字符对象的话,这就会产生难以接受的运行开销,显然这是不合理也是没必要的。由于文档字符就是那么些字母、数字或符号,完全可以让所有相同的字符都共享同一个对象,比如所有用到‘a’的字符的地方都使用一个共享的‘a’对象,这就可以节约大量的内存。”

OK,最后一位,代理小姐,请对比一下你外观小姐,有哪些不同?与适配器小姐又区别在何处?”迪米特问道。

代理没有想到会问这样一个问题,而旁边就站着外观和适配器,如果说得不好,显然就是很得罪人的事,她思考了片刻,说道:“代理与外观的主要区别在于,代理对象代表一个单一对象而外观对象代表一个子系统;代理的客户对象无法直接访问目标对象,由代理提供对单独的目标对象的访问控制,而外观的客户对象可以直接访问子系统中的各个对象,但通常由外观对象提供对子系统各元件功能的简化的共同层次的调用接口[R2P]”代理停了一下,然后接着说,“至于我与适配器,其实都是属于一种衔接性质的功能。代理是一种原来对象的代表,其他需要与这个对象打交道的操作都是和这个代表交涉。而适配器则不需要虚构出一个代表者,只需要为应付特定使用目的,将原来的类进行一些组合[DP]《大话设计模式》

“下面有请六位评委写上您们认为表现最好的模式小姐。”GOF说道。

桥接

适配器

外观

适配器

桥接

外观

“哦,各位来宾,观众朋友们,第二场结构型模式的比赛真是相当精彩,各位选手也都实力相当,难分伯仲,现在出现了‘桥接’、‘适配器’、‘外观’的比分均为两分的相同情况。根据比赛规则,她们三位需要站上PK台,进行PK。三位有请。”

“下面请三位各自说一说你比其他两位优秀的地方。适配器小姐先来。”

适配器说:“我主要是为了解决两个已有接口之间不匹配的问题,我不需要考虑这些接口是怎样实现的,也不考虑它们各自可能会如何演化。我的这种方式不需要对两个独立设计的类中任一个进行重新设计,就能够使它们协同工作[DP]

“非常好,下面有请桥接小姐。”

“我觉得我和适配器小姐具有一些共同的特征,就是给另一对象提供一定程度的间接性,这样可以有利于系统的灵活性。但正所谓未雨绸缪,我们不能等到问题发生了,再去考虑解决问题,而是更应该在设计之初就想好应该如何做来避免问题的发生,我通常是在设计之初,就对抽象接口与它的实现部分进行桥接,让抽象与实现两者可以独立演化。显然,我的优势更明显。[DP]

OK,说得很棒,外观小姐,您有什么观点?”

“首先我刚听完两位小姐的发言,我个人觉得她们各自有各自的优点,并不能说设计之初就一定比设计之后的弥补要好,事实上,在现实中,早已设计好的两个类,过后需要它们统一接口,整合为一的事例也比比皆是。因此桥接适配器是被用于软件生命周期的不同阶段,针对的是不同的问题,谈不上孰优孰劣。然后,对于我来说,和适配器还有些近似,都是对现存系统的封装,有人说我其实就是另外一组对象的适配器,这种说法是不准确的,因为外观定义的是一个新的接口,而适配器则是复用一个原有的接口,适配器是使两个已有的接口协同工作,而外观则是为现存系统提供一个更为方便的访问接口。如果硬要说我是适配,那么适配器是用来适配对象的,而我则是用来适配整个子系统的。也就是说,我所针对的对象的粒度更大。[DP]

“各个观众朋友们,在评委宣布结果之前,希望您能通过浏览器给她们投票,IE用户,Firefox用户,……,您的支持将是对当前选手的最大鼓励,最终获得票数最多者同样可以进级决赛。现在插播一段广告。”主持人GOF说道。《大话设计模式》

此时场下观众席中的两位,ADO.NETHibernate已经争论得不可开交。

Hibernate :“哈,你我看好的人都在PK台上,不过我相信桥接一定会赢。”

ADO.NET:“那可不一定,没出结果之前,别乱下结论,桥接老说适配器不如她,你没见评委在摇头吗?”

Hibernate :“我坚信桥接一定会赢,你要是不服,我加赌50,也就是150。”

ADO.NET:“哟哟哟,就加50,神气什么呀,要赌就赌大一些,1000,我赌适配器进级。”

Hibernate :“1000太多了点了,500吧。”

ADO.NET:“我赌1000,我赢了,你给我1000,我输了,我给你500。”

Hibernate :“小子,你也太狠了。赌,10001000。——评委呀,你们一定要看清楚呀,桥接才是真正的美女呀。”

ADO.NET:“哼,走着瞧吧。”

回到现场,“下面有请单一职责先生宣布评委的决定。”GOF大声说道。

“根据我们六位评委的讨论,做出了艰难的决策,最终统一了思想,一致决定,”单一职责停了停,“外观小姐晋级。”

外观小姐眼含泪光,但却保持着镇定,显然胜利的喜悦并没有让她失去常态。

适配器桥接都非常失望,想哭,却又不得不强忍住泪水,强颜欢笑,对外观表示祝贺。

场下的两位看不出什么失望,反而都有些高兴。

ADO.NET:“我没赢,也没让你赢,这次算是打平。”

Hibernate :“没想到让这个小黑马冲了出来,真是奇怪呀。”《大话设计模式》


(未完待续)

posted on 2007-11-17 10:33  伍迷  阅读(3438)  评论(14编辑  收藏  举报

导航