模式与实践

Patterns and Practice

Copyright © 1996-2005 Artima Software, Inc. All rights reserved

http://www.artima.com/lejava/articles/patterns_practice.html

模式与实践

Erich Gamma的一次谈话,第四部分

Bill Venners
Jun 21, 2005

翻译:lxwde

摘要

在这次采访中,Erich Gamma(里程碑式的书籍《设计模式》的作者之一)和Bill Venners谈论了设计模式是如何成为成对的问题解决方案(problem solution pair),设计模式如何帮助你理解意图(intent)和折衷(tradeoffs),以及如何通过实践成为一个好的设计师。

Erich Gamma是在1995年作为畅销书籍《设计模式可复用面向对象软件的基础》(Addison-Wesley, 1995) [1]合著者而跃上软件业界舞台的。这项具有里程碑意义的工作经常被援引为四人帮GoF的书该书针对通常的设计问题分类整理出了23种特定的解决方案。1998年,他和Kent Beck组成团队开发JUnit[2],这成为Java社区事实上的单元测试工具。Gamma现在是IBM的一名杰出工程师,他在位于瑞士苏黎世的IBM Object Technology InternationalOTI)实验室工作。他担任Eclipse社区的领导工作,负责Eclipse平台[3]上与Java开发相关的事务。

20041027Bill Venners 在加拿大温哥华举行的OOPSLA会议上遇到了Erich Gamma。在这次采访中这次采访的内容将分多次在Artima DeveloperLeading-Edge Java频道刊登出来),Gamma讲述了软件设计中深层次的东西。

  • 第一部分如何使用设计模式, Gamma给出了他对于如何正确思考和使用设计模式的看法,并且描述了模式库比如GoFAlexandrian的模式语言之间的差异。

  • 在第四部分里,Gamma谈论了设计模式是如何成为问题及其解决方案的(problem solution pair),设计模式如何帮助你理解意图(intent)和折衷(tradeoffs),以及如何通过实践成为一个好的设计师。

设计模式是问题及其解决方案

Bill Venners: 我对于面向对象编程最早的深刻认识来自于阅读Scott Meyers的《Effective C++》。在那本书里他有一条指导原则是说,“请确定公共继承表示的是‘是一个(is-a)’这种模型”那条原则帮助我第一次真正理解了继承。然而,《Effective C++》稍后有一条指导原则说,“通过组合来表示‘有一个(has-a)’或者‘借用某某来实现(is-implemented-in-terms-of)’这两种模型”这条原则并没有并没有为我弄明白如何使用组合提供太大的帮助。

GoF那本书里,我找到了几个关于使用组合的更加具体的说明(prescriptions)。GoF谈到用组合来模拟诸如“适配一个(adapts-a)”、“代理一个(proxies-a)”和“装饰一个(decorates-a)”等关系。如果你看看GoF那本书的UML图,它们很多看起来是类似的。它们中的大多数都通过接口继承使用组合。那些模式的区别之处在于你试图要通过组合和继承关系来解决的问题。即使类图可能看起来比较相象,设计意图也是不同的。设计意图在设计模式里充当什么样的角色呢?

Erich Gamma: 模式经常是一个可以被应用于某个特定上下文的问题及其解决方案problem-solution pair)。尽管不同的设计模式所提供的解决方案可能看起来是类似的,但是它们所解决的问题是不同的。实际上,大体上看from ten thousand meters???)大多数模式通过添加一个间接层(indirection)来解决某个问题。有趣的地方在于这个间接层是如何来的,而且尤其是为什么需要它。所以说如果你只是注意到问题的解决方案,那它并没有太大启发性并且看起来像是一样的东西。我们写《设计模式》的时候经常会有这种感觉——它们一开始看起来都像策略(Strategy)模式。

一开始我们只是描述解决方案。我们有一个大约20页的初步分类。有经验的开发者可以毫无问题的理解我们的意图并且以类似于下面这样的评论夸奖我们,“是的,我也这么用过”。然而,我们注意到其余的人要弄明白(我们的意图)就得花相当大的功夫了。我们展示了不同风格(flavor)的间接层。我们展示了代理(delegation)。但是基本上我们给出的是针对某个问题的一个解决方案。Alexander[4]对于模式的观点以及最初读者给予我们的反馈帮助我们不仅仅聚焦于解决方案上,而且也让我们关注问题部分。一个模式包括一个问题和一个解决方案,你需要两个都看到。例如,策略模式和状态模式有着相同的解决方案:你(把问题)代理给一个单独的对象,然后使用都符合某一接口的对象的类体系对行为进行改变。但是它们所解决的问题是不同的。策略模式是用来以插件的形式添加算法的,状态模式是用来在类的状态改变的时候改变它的行为的,像状态机那样。

理解意图(intent)和折衷(tradeoffs

Bill Venners: GoF那本书里,您说,“懂得了这本书里的设计模式可以更好的理解现有系统。”如何才能做到这一点?

Erich Gamma: 你可以使用模式(比不使用模式)更加简洁地解释一个现有系统。模式帮助你浓缩关于设计的对话。Kent Beck和我在我们的那本Eclipse书籍[5]最后一个章节所写的东西是这方面的一个好例子。我们用模式描述了Eclipse的某些设计。你可以达到的简洁程度实在是令人称奇。你可以说,“这是一个composite模式。”关于它你用不着再多说什么了。大家知道它是什么。

有趣之处在于,我们是针对Eclipse的一个早期版本做这种模式分析的,但是直到最近的版本这个分析依然是正确的。也就是说,虽然那些屏幕截图已经过时了,但是我们确定出来的那些模式依然有效。

一旦你了解到系统正在使用某组模式,而且你知道那些模式有哪些限制和职责,你就能更容易的理解采用这种解决方案的开发者的意图。模式不但告诉你(开发者的)意图,它还告诉你折衷的地方。当你知道了某个设计的局限性所在,你就可以更容易的成为一个诸如框架的可重用设计的好市民。可能发生的最糟糕的一件事情是,一开始你就对抗这个设计,因为你没有真正理解它到底是什么,非但不对它的意图表示敬意,你一开始就让人听起来有点像Frank Sinatra,“I'll do it my way

Bill Venners: 您刚刚说过模式告诉我们关于折衷的一些东西。您这是什么意思呢?

Erich Gamma: 设计从来都是关于折衷的。存在很多种选择而且每种选择都有不同的结果。做设计的时候,我是在不停地做决定。每个决定都有它的优点和缺点。这也是我们在写作《设计模式》的时候学到的一个经验教训。一开始我们对模式是如此的激动;我们只看到了正面的效果。直到一段时间以后有读者指出我们的做法是不切实际的。于是我们走了另外一条路,而且还讨论了职责。这时候我们还认识到,辨认出一个模式比实际把它写出来要简单的多。这里是一个例子:假如说你刚刚添加了策略模式,并且获得了更多的灵活性。但是它的代价是现在有了更多的对象和一个额外的间接层。对吧?工程上的每件事情都有它的代价。这就是我说的折衷的意思。模式的一个重要价值是它捕获了这些折衷,所以你就用不着再做一遍分析了。当你沿着一个设计流程走下来,模式就像路标一样。如果你走这条路,你就知道这里做了折衷。我想这种做法是很有价值的。

应用设计模式

Bill Venners: GoF那本书里您和您的合著者们说,“懂得这些设计模式可以让你成为一个更好的设计师。”如何才能做到?我不仍然需要知道什么时候该应用它们?

Erich Gamma: 是的,不要把你的大脑关掉;仍然需要你的创造性。什么时候该应用某个模式并不总是很清楚的。此外,你还需要知道该应用某一模式的哪个变体,以及如何对模式进行调整。你常常需要针对你的特定问题对某个模式进行调整。

这里我可能要对《设计模式》做一点澄清——在那本书里我们只告诉大家什么时候该应用一个模式,而从来没有谈论到什么时候该移除一个模式。移除一个模式可以让系统变的更简单而且一个简单的解决方案总是更好的。找到简单的解决方案是真正的挑战所在。

Bill Venners: 许多人都想成为更好的设计师,他们想要通过这本书来帮助他们达到这个目的,但是只是阅读这本书并不能。。。。。。

Erich Gamma: 。。。。。。并不能造就一个好的设计师。我同意,仅仅通过阅读书籍学习模式——以及更为重要的东西,设计——其实并不管用。另外,现在还有其它几本有趣的模式书籍,所以读完GoF那本书以后不要停止关于模式的阅读。

Bill Venners: 什么才能造就一个好的设计师?他们需要做什么?

Erich Gamma: 除了阅读书籍,你需要阅读并理解大量的代码,看看现有系统是如何解决一个特定问题的以及有经验的设计者是如何做的。基本上,设计模式所做的就是告诉你这些开发者已经完成了哪些东西。但是,仅仅看书是不够的。你通过模仿优秀的开发者所做的工作才能成为一个大师。有许多可供利用的吸引人的开源项目可以作为有趣的阅读材料。Eclipse只是其中一个。为一个开源项目贡献自己的一份力量也不是什么坏事。你不但可以学到某种特定的开发流程,而且你还会学到如何在一个开发小组里交流讨论某个设计。作为一个好的设计师,你不仅需要有好的设计,而且你还需要与人交流并且捍卫你的设计。你必须得实践,在某种程度上得像个学徒。随着时间的推移你也会成为一个经验丰富的设计师。

实践,实践,再实践

Bill Venners: GoF那本书里,您写到,“认识到模式是一种解决方案、是一个能够被调整和重用的技巧是非常容易的。而要想明白什么时候(使用它)是合适的(指辨别出它所解决的问题和它能成为最优解决方案的上下文)就要困难的多了。”设计新手该如何应付这个问题。假如说他们通读了那本书,而且他们也理解了那些模式。现在他们要做自己的工作了。他们怎么才能知道什么时候使用某个模式是合适的,什么时候他们是在陷入“模式症”而试图使用尽可能多的模式?

Erich Gamma: 很不幸,这里面很多东西你只能通过身体力行而在后来学到,得等到你能够回头(用老练的眼光)看看你所做的东西的时候。如果我是一个开发新手,我会希望有一个师傅(mentor)或者伙伴(buddy)。我会和他们一起编程,师傅会说,“等一下,现在这东西太丑陋了,”或者“嗨,你刚刚把另一个地方写过的东西又写了一遍”。师傅会很快给我反馈并且就更深入的东西给我提供指导。这正好是成对编程(pair programming)的一种形式。它同样也是你提高技术的一个绝好的方法。我经常从成对编程的过程中学到东西,而且我希望能够更经常的从事这件事情。

底线是你得是通过编程学习模式。而且,不能仅仅是那些小儿科的例子;还得有现实中的例子。但是,不,你不可能仅仅通过阅读书籍学习模式。只靠一本书你可能一开始就没有完全理解它们。一旦你开始在你自己的编程问题里应用某个模式,你就开始更好的理解它们了,而且也为下一个学习周期做好了准备。

下周

613号,星期一,请您回来看与Erich Gamma这次谈话的下一部分。如果你想收到Artima.com上新文章每周简报的电子邮件请订阅 Artima Newsletter

反馈

对本文中讨论的设计模式话题有自己的观点么?那么请到文章论坛里讨论这个话题, The True Utility of Design Patterns.

资源

[1] Erich Gamma是《设计模式:可复用面向对象软件的基础》的合著者之一,可以在Amazon.com上找到这本书                                 
http://www.amazon.com/exec/obidos/ASIN/0201633612/

[2] Erich Gamma JUnit的作者之一JUnit是事实上的Java单元测试标准工具
http://www.junit.org/index.htm

[3] Erich Gamma 领导Eclipse平台上与Java开发相关的事务
http://www.eclipse.org/

[4] Christopher Alexander 在他的著作中描述了建筑学上的模式比如《 A Timeless Way of Building 牛津大学出版社1979。可以在Amazon.com上找到 :
http://www.amazon.com/exec/obidos/ASIN/0195024028/

[5] Contributing to Eclipse: Principles, Patterns, and Plug-Ins, 作者是 Erich Gamma Kent Beck, 这本书可以在Amazon.com上找到
http://www.amazon.com/exec/obidos/ASIN/0321205758/
 

关于作者

Bill Venners Artima软件公司的主席兼Artima Developer的主编。他是《Inside the Java Virtual Machine》一书的作者,该书从面向程序员的角度讲述了Java平台的架构和内幕。他在JavaWorld杂志上广受欢迎的专栏覆盖了Java内幕,面向对象设计,以及Jini。从Jini启动以来,Bill就活跃在这个社区。他领导Jini社区的ServiceUI项目,这个ServiceUI API成为连接用户接口和Jini服务之间既成事实的标准方法。Bill还被选为Jini社区最初的技术监管委员会(TOC)的一员,他担任这个职务期间帮助定义了社区的管理流程。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值