设计模式三重天[之二]
写作背景:
一直在看关于设计模式的书并不断的实际工作中努力实践,同时也看到了播客园上设计模式
团队文章热火朝天的研究和讨论。心里非常高兴,在国内设计模式的研究和使用还不是很丰富和
完善的今天,这种讨论无疑会对每个园中的个体还是播客园整体实体的提升有着重大的意义,我
非常希望以后想研究.NET程序的人只要知道两个网址就能完成工作中90% 的知识查询,一个是微
软的MSDN,一个就是播客园。
注:本文不是专门研究某一种设计模式,而是从全局出发,通过本人将近 1年半的学习和研
究设计模式后形成的一些个人观点在这里进行一下阐述,因为个人的能力有限,这里只是希望与
大家交流设计模式的学习心得,如果有些观点与您的相似或不同,欢迎大家与我联系。如某些观
点让某些人不舒服,欢迎拍砖。
接上文..
第二重: [模式合成]
在学习并使用了一段时间的设计模式后(大约四个月到半年),发现设计模式在代码形式上
的一些近似完全可以成为整合一种或两种以上设计模式的桥梁 [当然也要参见和在上面说的那种
模式之间关联图上的说明]。这时在使用设计模式上就要有一定的突破了, 既不能死守代码解释
固步自封,也是能过于激近,甚至把某种设计模式上的优势人为去掉而让自己的代码取而代之,
这都会让自己最后设计的的东西不令人满意[特别是你自己]。那么什么时候才能确定要采用模式
合成呢,我这里给出两个建议,这也是我在去年做一个计费系统时所采用的:
建议1:
当满足用户需求所使用的一种模式而很难达到和应付其未来需求转变时所带来的代码修改和
维护量时,这就要考虑模式合成了。但这要建立在充分发掘用户需求的基础上。
因为一切取决了用户需求,如何最大程度的挖掘出用户的需求,或者是与用户一起研究出最
佳的系统业务模式,这对于系统的设计是至关重要的,必竟好的需求分析是项目成功的起点。
这个阶段一定要认真找出系统的功能模块以及用户需求中一些不明确的东西,因为也许就是这个
不明确,不清楚在被系统分析员和客户忽略后,在项目的交付时会闹出不少“笑话”。虽然设计
模式从程序员的角度找到了一条满足用户不断变化需求的捷径,但是如果用户的需求太离谱或很
模糊,那设计模式也只能说是“巧妇难为无米之炊”了。关于如何发现需求的方法太多了,我现
在使用的是ICONIX方法,它号称是只用UML 20%的功能图表实现其80%-90%功能的一种分析方法。
例如:本人在一个计费系统时就遇到过类似问题,一方面是计费时使用的策略管理员可以不
断生成订制或编辑修改,而另一方面 WEB用户只想在不断变化的用户策略基础上以合格价格购入
商品,而且用户将来可以不仅是本站,还可以是任何第三方[合作伙伴]所提供的。这让人感到系
统的复杂性很高。如果按通常的设计模式,也许大家会使用如Strategy模式来实现其计费策略上
的不断变化更新,水平更好的一些程序员会使用如依赖注入, IOC方式来实现计费策略给系统带
来的在业务流程上和设计上的便利。但是当用户的来源不明确的情况下,用户来源不断增加,同
时要求计费策略上也要有相应的体现时,原有的计划方案就有些相形见肘了。还好有一个Bridge
桥模式能够解决这个问题,因为该模式的应用背景恰恰是“将抽象部分与它的实现部分分离,使
它们都可以独立地变化”。当把WEB用户这一边的变化放在了桥模式的RefineAbstraction位置上
时,系统的结构变得非常清晰,而桥的另一半(右面Implementor)完全是基于Strategy模式。
最终,这个项目完成了,结构上也只是像是一个大桥联系着用户和计费策略。
我只想说的就是如果一个局限于代码的表现形式或模式的固有外观的话,那只能让那四位大
师望文生叹了,因为他们所做出的这些模式只是非常原子级的。我认为:他们是希望我们用这些
类似于积木模式来搭建一个应用系统。而是不让这些模式各自为战,今生不见的。
建议2:
当一种模式所满足的用户变化需求只能达到某个程度上时,而其它的功能要自己去写,这时
开始担心自己的程序无法在将来维护时很难理解,这时也可以使用模式合成。
这时的合作目的就不是建议1中所提到的应用背景了,这完全是出于做系统结构的优化,甚至
是局部重构。以便让你的程序在可读性和可维护性以及便于调试上找到一个平衡点。
就像一位UML大师说的,当设计模式成为一种语言时,特别是在程序员中广泛使用时,会极大
地增强交流的效率和准确性。
比如说,我在一个购物车上使用了observer模式,因为用户在网上购物时,只在点击支付时
才会进行商品结算,同时也可以使用网站提供的计算器进行运算。这个功能在VS2003上可以使用
代理委托链(Delegate chain)的形式加以实现,但如果想在购物车上施加更多的控制,如打扣,
返虚拟币的功能时,就要使用相对复杂一些的设计了。而观察者模式的应用背景就是“定义对象
间的一种一对多的依赖关系 ,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并
被自动更新”,这个思想在支付打拆时很好使用,你可以把购物车做成一个对象,而对商品作成
另一个对象,二者是1:n的关系,当用户支付时,可以对车中的商品进行分别计费[打折]或总额
计费[打折],而把观察者模式下的Notify()函数直接放在结算按钮的ONClick事件下(也可使用
delegate进行关联。)
上面所述是仁者见仁,智者见智。也许一百个程序员有一百种方案,但当我说出上面的设计
思想时,研究过observer模式的人一定很快就能找出代码的组织结构和设计上的一些问题,这会
节省许多交流上的时间花费,同时提高开发系统的效率,因为observer的框架大家都非常清楚,
只要按照规范开发就一切OK了。
建议3:
同时模式合成不仅在异种模式,即使在同种模式下也可以进行合成,只不过这块我觉得应该
是在重构Refactor阶段时使用。以使相同的模式,类似的功能模式下进行合并重组,以使代码进
行一步优化,同时也降低了BUG的发生率。“必定重复的代码就会重复着风险”。
当然,这一切都要建议在你对你要合成的模式有多深的了解。它们的应用背景,它们在设计
上,以及灵活性等方面所具备的优势。只有这样才是真正的好钢用在了刀韧上,否则就可能是画
虎不成反累犬了。
最后要说明的是,模式合成只不过是我的一个“自造之词”。 而这个阶段也不是学习模式的
最终阶段。相反,这一阶段要与第一阶段进行反复穿插,因为做模式合成会不停的让你考虑这么
做到底对与不对,如果这样做有什么后果。当你感到你以前对某种模式的理解有了不同的认识,
甚至完全推翻的话,那我首先要恭喜你了,因为你可能要产生质的飞跃了。这就像是哲学上的“
否定之否定”一样,你会在不断的否定中进入到更高的境界。
但这也不是最终的目标,因为这只是所谓的“小乘佛法”。如果要修练成“大乘佛法”,也
就是我说的第三重境界,还要不断学习研究。直至最后的“无模式”。
未完.....