时间:7月23日下午 17点 地点:小菜办公室 人物:小菜、公司开发部经理
“小菜,”开发部经理来到小菜的办公桌前,“最近我听说你在工作中,用到了很多设计模式,而且在你们同一项目组中引发了关于设计模式的学习和讨论,反响非常好。明天全公司要开关于如何提高软件质量的研讨会,我希望到时你能做一个关于设计模式的演讲。”
“我?演讲?给全公司?”小菜很惊讶于经理的这个请求,“还是不要了吧,我从来都没上过台给那么多人讲东西。我怕讲不好的。”
“没事,你就像平时和同事交流设计模式那样说说你在开发中的体会和经验就行了。”
“明天,时间太仓促了吧,来不及的。”小菜想法推脱。
“哈,某位大导演在他的近期的电影里不是已经向众人证实,身材是可以靠挤来获得的。同理可证,时间也是可以挤出来的,晚上抓紧一些,一定行的。就这么定了,你好好准备一下。”说完,经理就离开了小菜的办公桌。
“我……”小菜还来不及再拒绝,已经没了机会。
时间:7月23日晚上 22点 地点:小菜自己的卧室 人物:小菜
“讲什么好呢?”小菜使劲地想呀想,却没有头绪,“该死的大鸟,还不回来,不然也可以请教请教他。”
“真困”,小菜睡眼朦胧,趴到了桌上,打起盹来,不一会,进入了梦乡。《大话设计模式》
时间:未知 地点:未知 人物:很多
“来来来,快来报名了,超级设计模式大赛,每个人都有机会,每个人都能成功,今天你参加比赛给自己一个机会,明天你就成功还社会一个辉煌。来来来……”只见台子上方一很长的条幅,上写着“OOTV杯超级模式大赛海选”,下面一个帅小伙拿着话筒卖力地吆喝着。
“大姐、二姐,我们也去报名参加吧。”工厂三姐妹中最小的简单工厂说道。
“这种选秀比赛,多得去了,很多是骗人的,没意思。”大姐抽象工厂说。
“我觉得我们三姐妹有机会的,毕竟我们从小就是学这个出身。”二姐工厂方法也很有兴趣参赛。
“大姐,去吧,去吧。”简单工厂拉住抽象工厂的手左右摇摆着。
“行了行了,我们去试试,成就成,不成可别乱哭鼻子。”抽象工厂用手指点了一下简单工厂的鼻子,先打上了预防针。
“放心吧,我们都会成功的。”简单工厂很高兴,肯定地说。
三个人果然顺利通过了海选。但在决赛前的选拔中,工厂方法和抽象工厂都晋级,而简单工厂却不幸落选了。
“唔唔唔……唔唔唔……”简单工厂哭着回到了后台。
“小妹,别哭了,到底发生了什么?”工厂方法搂住她,轻声地问道。
“他们说我不符合开放-封闭原则的精神,”简单工厂哽咽地答道,“所以就把我淘汰了。”
“你在对每一次扩展时都要更改工厂类,这就是对修改开放了,当然不符合开闭原则。”抽象工厂说道,“行了,别哭了,讲好了不许哭鼻子的。”
“哇……哇……哇……”被大姐这么一说,简单工厂放声大哭。
“好了,没关系的,这次不行,还会有下次的。”工厂方法拍了拍她的后背安慰地说。
“二姐,你要好好加油,为我们工厂家族争光。”简单工厂握着工厂方法的手说,然后对着抽象工厂说,“大姐,哼,你老是说风凉话,祝你早日淘汰。”边说着,简单工厂却破涕为笑了。
“你这小妮子,敢咒我。看我不……”抽象工厂脸上带笑,嘴里骂着,举起手欲拍过去。
“二姐救我,大姐饶命。”简单工厂躲到工厂方法后面叫道。
三姐妹追逐打闹着,落选的情绪一扫而空。《大话设计模式》
“各位领导、各位来宾、观众朋友们,第一届OOTV杯超级设计模式大赛正式开始。”漂亮的主持人GOF出现在台前,话音刚落,现场顿时响起激昂的音乐热烈的掌声。
“首先我们来介绍一下到场的嘉宾。第一位是我们OOTV创始人,面向对象先生。”只见前排一位40多岁的中年人站了起来,向后排的观众挥手。
工厂方法在后台对着抽象工厂说:“没想到面向对象这么年轻,40岁就功成名就了。”
“是呀,他从小是靠做simula服装开始创业的,后来做Smalltalk的生意开始发扬光大,但最终让他成功的是Java,我觉得他也就是运气好。”抽象工厂解释说。
“运气也是要给有准备头脑的人,前二十年,做C品牌服装生意的人多得是了,结构化编程就象神一样的被顶礼膜拜,只有面向对象能坚持OO理念,事实证明,OO被越来越多的人认同。这可不是运气。”
“结构化编程那确实是有些老了,时代不同了,老的偶像要渐渐退出,新的偶像再站出来。现在是面向对象的时代,当然如日中天,再过几年就不一定是他了。”抽象工厂相对悲观。
“面向对象不是一直声称自己‘永远二十五岁’吗?”工厂方法双手抱拳放在胸前,坚定地说,“我看好他,他是我永远的偶像。”
“到场来宾还有,抽象先生、封装先生、继承女士、多态女士。他们也是我们这次比赛的策划、导演和监制,掌声欢迎。”主持人GOF说道。
工厂方法说:“啊,这些明星,平时看都看不见的,真想为他们尖叫。”
抽象工厂说:“我最大的愿望就是能得到抽象先生的签名,看来极有可能梦想成真了。”
两姐妹在那里入迷地望着前台,自说自话着。
“现在介绍本次大赛的评委,单一职责先生、开放封闭先生、依赖倒转先生、里氏代换女士、合成聚合复用女士、迪米特先生。”主持人GOF说道。
“那个叫开放封闭的家伙就是提出淘汰小妹的人。”抽象工厂对工厂方法说。
“嘘,小点声,他们可就是我们的评委,我们的命运由他们决定的。”工厂方法把食指放在嘴边小声地说。
“下面有请面向对象先生发表演讲。”主持人GOF说道。
面向对象大步流星地走上了台前,没有任何稿子,语音洪亮地开始了发言。
“各位来宾,电视机前的朋友们,大家好!(鼓掌)
感谢大家来为OOTV的超级设计模式大赛捧场。OO从诞生到现在,经历了风风雨雨,我面向对象能有今天真的也非常的不容易。就着这机会,我来谈谈面向对象的由来和举办此次设计模式大赛的目的。
软件开发思想经过了几十年的发展。最早的机器语言编程,程序员一直在内存和外存容量的苛刻限制下‘艰苦’劳作。尽管如此,当时程序员还是创造了许多令人惊奇的工程软件。后来,高性能的计算机越来越普及,它们拥有较多的内外存空间,编程也发展到一个较高的层次,不再对任一细节都斤斤计较,于是出现了各种高级语言,软件编程开始进入了全面开花的时代。
刚开始的高级语言编写,大多是面条式的代码,随着代码的复杂化,这会造成代码极度混乱。随着软件业的发展,面条式的代码是越来越不适应发展的需要,此时出现了结构化编程,即面向过程式的开发,这种方式把代码分割成了多个模块,增强了代码的复用性,方便了调试和修改,但是结构也相对复杂一些。面向过程的开发,把需求理解成一条一条的业务流程,开发前总是喜欢问用户‘你的业务流程是什么样的?’,然后他们分析这些流程,把这些流程交织组合在一起,然后再划分成一个又一个的功能模块,最终通过一个又一个的函数,实现了需求。这对于一个小型的软件来说,或许是最直接最简捷的做法。
而问题也就出在了这里。随着软件的不断复杂化,这样的做法有很大的弊端。面向过程关注业务流程,但无论多么努力工作,分析做得如何好,也是永远无法从用户那里获得所有的需求的,而业务流程却是需求中最可能变化的地方,业务流程的制定需要受到很多条件的限制,甚至程序的效率、运行方式都会反过来影响业务流程。有时候用户也会为了更好地实现商业目的,主动地改变业务流程,并且一个流程的变化经常会带来一系列的变化。这就使得按照业务流程设计的程序经常面临变化。今天请假可能就只需要打声招呼就行了,明天请假就需要多个级别管理者审批才可以。流程的易变性,使得把流程看得很重,并不能适应变化。
面向过程通过划分功能模块,通过函数相互间的调用来实现,但需求变化时,就需要更改函数。而你改动的函数有多少的地方在调用它,关联多少数据,这是很不容易弄得清楚的地方。或许开发者本人弄得清楚,但下一位维护代码者是否也了解所有的函数间的彼此调用关系呢?函数的修改极有可能引起不必要的Bug的出现,维护和调试中所耗费的大多数时间不是花在修改Bug上,而是花在寻找Bug上,弄清如何避免在修改代码时导致不良副作用上了。种种迹象都表明,面向过程的开发也不能适应软件的发展。
与其抱怨需求总是变化,不如改变开发过程,从而更有效地应对变化。面向对象的编程方式诞生,就是为解决变化带来的问题。
面向对象关注的是对象,对象的优点在于,可以定义自己负责的事物,做要求它自己做的事情。对象应该自己负责自己,而且应该清楚地定义责任。
面向对象的开发者,把需求理解成一个一个的对象,他们喜欢问用户‘这个东西叫做什么,他从哪里来,他能做什么事情?’,然后他们制造这些对象,让这些对象互相调用,符合了业务需要。
需求变化是必然的,那么尽管无法预测会发生什么变化,但是通常可以预测哪里会发生变化。面向对象的优点之一,就是可以封装这些变化区域,从而更容易地将代码与变化产生的影响隔离开来。代码可以设计得使需求的变化不至于产生太大的影响。代码可以逐步演进,新代码可以影响较少地加入。
显然,对象比流程更加稳定,也更加封闭。业务流程从表面上看只有一个入口、一个出口,但是实际上,流程的每一步都可能改变某个数据的内容、改变某个设备的状态,对外界产生影响。而对象则是完全通过接口与外界联系,接口内部的事情与外界无关。
当然,有了面向对象的方式,问题的解决看上去不再这么直截了当,需要首先开发业务对象,然后才能实现业务流程。随着面向对象编程方式的发展,又出现了设计模式、ORM、以及不计其数的工具、框架。软件为什么会越来越复杂呢?其实这不是软件本身的原因,而是因为软件需要解决的需求越来越复杂了。
面向过程设计开发相对容易,但不容易应对变化。面向对象设计开发困难,但却能更好的应对千变万化的世界,所以现代的软件需要面向对象的设计和开发。《大话设计模式》
(鼓掌)
设计模式是面向对象技术的最新进展之一。由于面向对象设计的复杂性,所以我们都希望能做出应对变化,提高复用的设计方案,而设计模式就能帮助我们做到这样的结果。通过复用已经公认的设计,我们能够在解决问题时避免前人所犯的种种错误,可以从学习他人的经验中获益,用不着为那些总是会重复出现的问题再次设计解决方案。显然,设计模式有助于提高我们的思考层次。让我们能站在山顶而不是山脚,也就是更高的高度来俯视我们的设计。
如今,好的设计模式越来越多,但了解他们的人却依然很少,我们OOTV举办设计模式大赛的目的一方面是为了评选出最优秀的设计模式,另一方面也是希望让更多的人了解她们,认识她们,让她们成为明星,让她们可以为您的工作服务。
祝愿本届大赛圆满成功。谢谢大家![DPE]”(鼓掌)
正在此时,突然一个人双手举着一块牌子冲上了讲台,纸牌上写着“Service-Oriented Architecture(面向服务的体系架构SOA)”,口中大声且反复地说道:“抵制Object-Oriented,推广Service-Oriented,OO已成往事,SOA代表未来。”
这突如其来的变化,让全场哗然,很多人都交头接耳,说着关于SOA与OO的关系。只有面向对象先生依然站在讲台上,微笑不语,显然久经风雨的他对于这种事早已见怪不怪。保安迅速带着此人离开了会场。会场渐渐又恢复了安静。
“下面宣布一下比赛规则。”GOF的声音再次响起,“本次大赛根据模式的特点,设置了三个类别,分别是创建型模式、结构型模式和行为型模式,但由于有11位选择了行为型模式,人数过多,所以行为型模式又分为了两组。也就是说,我们将选手共分为了四组,所有的选手都将首先参加分组比赛,每组第一名将参加我们最终设计模式冠军的争夺。选手的分组情况,请看大屏幕。”
“下面我们就有请,单一职责先生代表评委宣誓。”
此时,几位评委站了起来,单一职责先生拿起事先写好的稿子,缓慢地说道:“我代表本届大赛全体评委和工作人员宣誓:恪守职业道德,遵守竞赛规则。严格执法,公正裁判,努力为参赛选手提供良好的比赛氛围和高效优质服务,维护公正的评委信誉。为保证大会的圆满成功,做出我们应有的贡献!宣誓人:单一职责。”
“宣誓人:开放封闭”
“宣誓人:依赖倒转”
……
“下面有请策略模式小姐代表参赛选手宣誓。”
“为了展示面向对象的优点和思想,为了编程的光荣和团队的荣誉,我代表我们全体参赛选手,将弘扬‘可维护、可扩展、可复用、灵活性好’的OO精神,严格遵守赛事活动的各项安排,遵守比赛规则和赛场纪律,尊重对手,团结协作,顽强拼搏,赛出风格,赛出水平,胜不骄,败不馁,尊重裁判,尊重对方,尊重观众。并预祝大赛圆满成功。”《大话设计模式》
“现在比赛正式开始,有请第一组参赛选手入场,并进行综合形象展示。”
“第一组创建型选手,他们身穿的是Java正装进行展示。”
“1号选手,抽象工厂小姐,她的口号是提供一个创建一系列或相关依赖对象的接口,而无需指定它们具体的类。[DP]”
1号选手 抽象工厂(Abstract Factory)
“2号选手,建造者小姐,她的口号是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。[DP]”
2号选手 建造者(Bulider)
“3号选手工厂方法小姐向我们走来,她声称定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂模式使一个类的实例化延迟到其子类。[DP]”
3号选手 工厂方法(Factory Method)
“4号选手是原型小姐,她的意图是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。[DP]”
4号选手 原型(Prototype)
“5号选手出场,单例小姐,她提倡简捷就是美,保证一个类仅有一个实例,并提供一个访问它的全局访问点。[DP]”
5号选手 单例(Singleton)
此时只见场下一帮Fans开始热闹起来。
简单工厂带领着抽象工厂和工厂方法的粉丝们开始齐唱,“咱们工厂有力量,嗨!咱们工厂有力量!每天每日工作忙,嗨!每天每日工作忙,……哎!嗨!哎!嗨!为了咱程序员彻底解放!”
“单例单例,你最美丽,一人创建,全家获益。”单例的Fans同样不甘示弱地喊着口号。
观众席中还有两位先生安静地坐在那里,小声地聊着。
“你猜谁会胜出?”ADO.NET对旁边的Hibernate说。
“我觉得,抽象工厂可以解决多个类型产品的创建问题,就我而言,同一对象与多个数据库ORM就是通过她来实现的。我觉得她会赢。”Hibernate坚定地说。
“你也不看看,抽象工厂那形象,多臃肿呀,身上类这么多。做起事来一定不够利索。”ADO.NET不喜欢抽象工厂。
“那你喜欢单例?”Hibernate问道。
“单例又太瘦了。过于骨感也不是美。我其实蛮喜欢原型那小姑娘的,我的DataSet只要调用原型模式的Clone就可以解决数据结构的复制问题,而Copy则不但复制了结构,连数据也都复制完成,很是方便。”
“那你不觉得建造者把建造过程隐藏,一个请求,完整产品就创建,在高内聚的前提下使得与外界的耦合大大降低,这不也是很棒的吗?”
“问题是又有多少产品是相同的建造过程呢?再说回来,你造什么对象,不还是需要new吗?”
“哈,从new的角度讲,工厂方法才是最棒的设计,它可是把工厂职责都分了类了,其他几位不过是她的变体罢了。”
“有点道理,看来创建型这一组,工厂方法有点优势哦。”《大话设计模式》
“下面有请评委提问。”主持人GOF待五位选手出场亮相之后接着说。
“请问抽象工厂小姐,为什么我们需要创建型模式?”开放-封闭先生问道。
只见抽象工厂思考了一下,说道:“我觉得创建型模式隐藏了这些类的实例是如何被创建和放在一起,整个系统关于这些对象所知道的是由抽象类所定义的接口。这样,创建型模式在创建了什么、谁创建它、它是怎么被创建的,以及何时创建这些方面提供了很大的灵活性[DP]。”
“请问原型小姐,你有什么补充?”依赖倒转对着原型问道。
原型显然没想到突然会问到她,而且对于这个问题,多少有点手足无措,她说:“当一个系统应该独立于它的产品创建、构成和表示时,应该考虑用创建性模式。建立相应数目的原型并克隆它们通常比每次用合适的状态手工实例化该类更方便一些[DP]。”
“哈,这可能是我们需要原型的理由。”依赖倒转说道,然后转头问建造者,“请谈谈你对松耦合的理解。”
建造者对这个问题一定是有了准备,不慌不忙,说道:“这个问题首先要谈谈内聚性与耦合性,内聚性描述的是一个例程内部组成部分之间相互联系的紧密程度。而耦合性描述的是一个例程与其他例程之间联系的紧密程度。软件开发的目标应该是创建这样的例程:内部完整,也就是高内聚,而与其他例程之间的联系则是小巧、直接、可见、灵活的,这就是松耦合[DPE]。”
“那么你自己是如何去实践松耦合的呢?”依赖倒转接着问。
“我是将一个复杂对象的构建与它的表示分离,这就可以很容易地改变一个产品的内部表示,并且使得构造代码和表示代码分开。这样对于客户来说,它无需关心产品的创建过程,而只要告诉我需要什么,我就能用同样的构建过程创建不同的产品给客户[DP]。”
“回答得非常好,现在请问单例,你来说说看你参赛的理由,你与别人有何不同?”单一职责问道。
单例小姐有些羞涩,停了一会,才开口说:“我觉得对一些类来说,一个实例是很重要的。一个全局变量可以使得一个对象被访问,但它不能防止客户实例化多个对象。我的优势就是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且我还提供了一个访问该实例的方法。这样就使得对唯一的实例可以严格地控制客户怎样以及何时访问它[DP]。”
“工厂方法,请问你如何理解创建型模式存在的意义?”合成聚合复用问道。
此时只听场下一声音叫道,“二姐加油”,原来简单工厂在观众席上喊叫呢。工厂方法对着观众席微笑了一下,然后非常有信心地答道,“创建型模式抽象了实例化的过程。它们帮助一个系统独立于如何创建、组合和表示它的那些对象。创建型模式都会将关于该系统使用哪些具体的类的信息封装起来。允许客户用结构和功能差别很大的‘产品’对象配置一个系统。配置可以是静态的,即在编译时指定,也可以是动态的,就是运行时再指定。[DP]”
“那么请问你与其他几位创建型模式相比有什么优势?”
“我觉得她们几位都可能设计出比我更加灵活的代码,但她们的实现也相对就更加复杂。通常设计应该是从我,也就是工厂方法开始,当设计者发现需要更大的灵活性时,设计便会向其他创建型模式演化。当设计者在设计标准之间进行权衡的时候,了解多个创建型模式可以给设计者更多的选择余地。[DP]”
几位评委都在不住地点头,显然,他们非常肯定工厂方法的回答。《大话设计模式》
“下面有请几位评委写上您们认为表现最好的模式小姐。”GOF说道。
“单一职责先生,您的答案是?”
只见单一职责翻转纸牌,上面写着“单例”。
“非常好,单例小姐已有一票。”
“开放封闭先生,您的选择是?”
“工厂方法。我觉得工厂方法能使得我们增加新的产品时,不需要去更改原有的产品体系和工厂类,只需扩展新的类就可以了。这对于一个模式是否优秀是非常重要的判断标准,我选择她。”开放封闭说道。
“OK,工厂方法小姐也有一票了。”
……
“工厂方法小姐再加一票。”
……
“工厂方法小姐一共有五票。成功晋级,恭喜你。”GOF宣布完,只见工厂方法抱住了旁边的抽象工厂泪流满面,喜极而泣。下面的简单工厂和一帮工厂方法的小Fans们欢呼雀跃。而其他模式的Fans们低头不语,个别竟然已潸然泪下。
“好的,各位来宾,观众朋友们,第一场的比赛现在结束,工厂方法成功晋级,但其他四位选手并不等于没有机会,希望您能通过浏览器给她们投票,IE用户,请发送OO加选手编号到www.ootv.com,Firefox用户请发送OO加选手编号到www.ootv.net,其他浏览器用户请发送OO加选手编号到www.ootv.org,您的支持将是对落选选手的最大鼓励,最终获得票数最多者同样可以进级决赛。下面休息一会,插播一段广告。”
ADO.NET开始发牢骚:“什么最大鼓励,根本就是电视台在骗钱。”
“你不发拉倒,我可要给抽象工厂投上一票了。”Hibernate说道。
“嗨,算了,反正也就一元钱,我给原型投上一票。”
“哥们,原型没戏了,投抽象工厂吧,这样她进级了,你的钱也不白花。”
“呸,你怎么知道抽象工厂会比原型的票数多,大家都不投她,她能成功吗?我不但投原型,而且要投她十五张票(最高限额)。”ADO.NET坚持道。
“我碰到神经病了。你去打水漂去吧,我不陪你。”《大话设计模式》
生活还在继续,编程不会结束。每天晚上,我们程序员继续对程序、对爱情、对理想、对人生的讨论和思考。
程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其实我是一个程序员。