本章介绍设计模式的概念。
在本章,
l 我讨论设计模式在建筑学中的起源以及它们如何被应用于软件设计的学科中。
l 我讨论学习设计模式的动机。
设计模式是面向对象技术的最前沿部分。面向对象的分析工具、书籍以及研讨会都包含着设计模式。有关设计模式的学习团体比比皆是。通常有着这样的建议,人们只有在掌握了基本的面向对象技能之后才去学习设计模式。我却发现反面才是真的:在学习面向对象技能的初期便学习设计模式,这对提高对面向对象分析和设计的理解大有裨益。
在本书的整个剩余部分,我将不仅仅只讨论设计模式,还会讨论它们是如何展示和巩固面向对象原则的。我希望能提高你对这些原则的理解,并阐明为什么这里讨论的这些设计模式就代表着好的设计。
本章的部分内容看起来或许有些许抽象或者哲学。但是,请给它一个机会!它为你理解设计模式打下基石。对它的理解将会增强你对新模式的理解能力以及和它们相处的能力。
我的很多想法来自Christopher Alexander的《建筑的永恒之路》[1]。我将在整本书中讨论这些想法。
设计模式起源于建筑学和人类学多年以前,一位名为Christopher Alexander的建筑师问他自己,“质量是客观的吗?”美,真实存在于观看者眼中吗?或者,人们一致同意某些事物是美的而某些事物不美吗?现在,Alexander感兴趣的这种特殊形式的美成为建筑质量的一种:是什么让我们得知何时一个建筑设计才是好的?比如,如果一个人正要为一个房子设计一个入口,他或她怎么知道这个设计是好的?我们能够分辨出好的设计吗?存在一个用作判断的客观根据,一个描述我们一致意见的依据吗?
Alexander假定在建筑体系中存在这样一个客观根据。判断建筑之美不是一个简单的格调问题。我们能够通过一个可测量的客观根据来描述美。
文化人类学的学科发现了同样的东西。其工作主体提出,在什么被认为是一个好的设计,什么是美这一问题上,同一文化内的个体将会赞同大众的意见。文化对好的设计做出超越个人信仰的评判。我相信存在超越的模式,用作评价设计的客观根据。文化人类学的一个主要分支便在寻找模式来描述文化的行为与价值。[2]
设计模式背后的主张便是软件系统的质量也能被客观地度量。
如果你赞同识别并描述一个高质量的设计是有可能的,那么你如何去创造一个这样的设计?我似乎看见Alexander这样问他自己,
什么东西存在于高质量设计之中,却不存在于低质量设计之中?
以及
什么东西存在于低质量设计之中,却不存在于高质量设计之中?
这些问题起源于Alexander的信仰:如果设计中的质量是客观的,那么我们就应该有能力识别出是什么让设计成为好的设计,又是什么让设计成为坏的设计。
通过对建筑、城镇、街道,以及事实上人们为自己建造的每一个其它的生活空间进行大量的观察,Alexander对这个问题进行研究。他发现对于特定的建筑创造,好的结构彼此之间存在着共同的东西。
即便是同样类型的建筑结构,它们也彼此不同。尽管如此,它们依然都可能是高质量的。
例如两个看起来结构上可能不同的走廊,它们都可能被认为是高质量的。它们可能在为不同的房屋解决不同的问题。一个走廊可能是从走道到前门的一个过渡,另一个入口可则能是热天时的一个纳凉之处;或者两个走廊可能在用不同的方式解决一个共同的问题(过渡)。
Alexander明白这点。他知道结构不能脱离它们要解决的问题。因此,在他识别并描述设计质量一致性的探索中,他认识到他必须查看设计于解决相同问题的不同结构。例如图5-1给出了区分一个入口通道问题的两个方案。
图5-1 结构看起来可能不同,但却依然解决一个共同的问题。
Alexander发现通过以这种方式缩小他的焦点——通过查看解决类似问题的结构——他能够辨别出存在于高质量设计之中的相似之处。他称这些相似之处为模式。
他将模式定义为“一个背景下的一个问题的一个解决方案。”
每个模式描述一个在我们的环境中一再出现的问题,接着描述其解决方案的核心,这样你便能将这个方案使用百万次而不需要以同样的方式做两遍。[3]
让我们复习Alexander的一些成果来说明这一点。在表5-1中,我将展示一段来自《建筑的永恒之路》[4]的摘录。这本优秀的著作简洁地介绍了模式的哲学。
表5-1 摘自《建筑的永恒之路》
Alexander说……
我的评语……
一个形体适宜的庭院,以同样的方式帮助人们在其中生活。
一个模式总是拥有一个名称、一个目标。这里,模式的名称是庭院,其目的是帮助人们在其中生活。
Consider the forces at work in a courtyard。最主要的是,人们寻求某种私人户外空间,在那里他们可以坐在天空之下看星星、晒太阳,或者养花。这是很明显的。
尽管有时这似乎显而易见,但清楚陈述被解决的问题还是很重要的。这是使用模式的首要原因。这便是此处Alexander为庭院所作的事情。
但是依然有更微妙的forces。比如,当一个院子用围墙围得太紧,没有向外的视角,人们就会感觉不舒服,并想要离开…他们需要向外看到一些更广阔更遥远的空间。
他指出一处使用简化方案的困难,接着,对刚才指出的问题,他给我们一个解决的办法。
或者再一次的,人们是习惯的产物。如果他们每天在日常生活中出入这个院子,它将变得日渐熟悉,成为一个自然的去处…这样被使用了。
有时候熟悉会阻止我们看到那些显而易见的东西。模式的价值在于,那些缺乏经验的人能够利用其他人在他们之前学得的东西:那些拥有一个优秀设计以及避免拙劣设计所必须包含的。
但是一个内部只有一条路的庭院,一个只有当你“想”去你才会去的地方,是一个不熟悉的地方,往往会被弃置不用……人们更多地是去那些熟悉的地方。
是否有一个过渡的空间——一条走廊或者游廊,在顶盖之下,但却开放于空中——在心理上,这是介于室内和室外之间的一个折中,使得将你带到庭院之中变得容易简单的多……
对于建造一个大庭院可能会被忽视的挑战,他建议了一个解决方案。
当一个庭院有一个视角,能够对外看到一个更大的空间,有来自不同房间的交叉路,并且拥有一条游廊或者走廊,这些forces就能够解决它们自己。那向外的视角让人舒适,交叉路有助于产生习惯感,走廊让频繁出去变得容易……并且这个庭院逐渐变成一个习惯上舒适的场所。
……并且会告诉我们它为什么是强大的。
我们来做个复习。Alexander说模式的描述包含四个条款:
l 模式的名字
l 模式的目的,它解决的问题
l 我们如何达到目的
l 为了达到目的我们必须考虑的限制和forces
Alexander假定模式能够解决人们事实上将会遭遇到的每一个建筑问题。他进一步假定模式能被组合使用来解决复杂的建筑问题。
关于模式如何一起工作将会在本书后面被讨论。现在我将聚焦在他关于模式有助于解决特定问题的说法上。
从建筑学模式到软件设计模式建筑学里所有的这档子事究竟跟我们软件开发人员有何关联呢?
是这样的,20世纪90年代初期一些聪明的开发人员偶然发现Alexander的模式著作,他们想知道在建筑模式上为真的东西是否在软件设计上也为真。[5]
l 是否软件中一再出现的问题也能在某种程度上用同样的方式来解决?
l 是否仅在模式被识别出之后,就有可能通过模式来设计软件,基于它们来创造特定的解决方案?
这些人觉得这两个问题的回答都是“毋庸置疑的正确。”接下来便是去识别几个模式并开发出为新模式分门别类的标准。
虽然很多人在二十世纪九十年代早期就对设计模式产生着影响,但对这一缺乏经验的社区影响最大的书是Gamma,Helm,Johnson和Vlissides的《设计模式:可复用面向对象软件的基础》[6]。为了表彰这四位作者的重要工作,他们被广泛而亲切地冠以四人团的美名。
这本书有几个作用:
l 它将设计模式的想法应用于软件设计。
l 它描述了一个结构,并在这个结构之内分类和描述设计模式。
l 它归类了23个这样的模式。
l 基于这些设计模式,它假定了面向对象的策略和途径。
有一点很重要。这四位作者并没有创造出书中所描述的模式,而是识别出这些模式。因为模式已经存在于软件社区之中,它们反映了人们对特定问题之高质量设计的了解(注意和Alexander的工作的相似)。
今天,有几种描述设计模式的不同形式。由于这不是一本书写设计模式的书,所以我不会给出有关描述设计模式的最好结构的观点。然而,接下来在表5-2中所列举的条款需要被包含在任何的描述之中。
对我在本书中所介绍的每一个模式,我都会用一页来对描述这个模式的关键特性进行总结。
表5-2 模式的关键特性
条款
描述
名字
所有的模式都有一个唯一标示它们的名字。
意图
模式的目的。
问题
模式试图解决的问题
方案
模式是如何为所处背景之中的问题提供解决方案的。
参与者和协作者
模式所涉及的实体。
结果
使用模式的结果。研究使用这个模式的forces。
实现
模式能如何被实现。
注意:实现仅仅是模式的具体表现,不应该被解释为模式自身。
GoF参考
需要在四人团文字中查阅到更多信息的地方。
结果/Forces
术语结果被用于设计模式之中并且常常被误解。在日常用法中,结果一词通常带有贬义。(你永远不会听到某人说,“我中了六合彩!结果,我现在不必上班了!”)然而在设计模式社区中,结果一词仅表示原因和结果。即如果你用某某方法实现这一模式,this is how it will affect and be affected by the forces present.
为什么学习设计模式现在,你对设计模式有了一点点想法,可能还想问,“为什么学习它们?”这里有几个原因是显而易见的,也有几个原因则不是那么明显。
学习模式最常见的理由是因为模式允许我们:
l 重用解决方案——通过重用已经建立的设计,我在我的问题上获得领先并避免苦苦搜寻。我得学习他人经验的好处。我不必为总是一再重复出现的问题重新发明解决方案。
l 建立共同的术语表——交流和团队协作需要一个共同的词汇基础以及一个对问题的共同观点。在项目的分析和设计阶段,设计模式提供了一个共同的参考点。
然而,还有学习设计模式的第三个理由:
在设计和面向对象的过程中,模式给你一个看问题的高层视角。这把你从过早处理细节的暴政中解脱出来。
在本书的结尾,我希望你会同意这是学习设计模式的一个最大的理由。它将转换你的思维习惯并把你变成一个更强大的分析家。
为了说明这一好处,在此我要引述一段两个木匠关于如何为一些橱柜制造抽屉的谈话。[7]
想象两个木匠正在讨论如何为一些橱柜制造抽屉。
木匠1:你觉得我们该怎么样制造这些抽屉?
木匠2:嗯,做这样一个接头,我认为我们应该向下笔直切入木头,接着回头以45度角方向向上切割,再回头笔直下切,然后回头以另一个45度角方向向上切割,再回头笔直下切,接着……
现在,请你说说他们在谈论什么!
那不是一段令人费解的描述吗?木匠2究竟在作何指示?毫无疑问,细节阻碍着我们!让我们来理清他的描述。
木匠2说……
看来就像……
“嗯,做这样一个接头,我认为我们应该向下笔直切入木头,接着回头以45度角方向向上切割……”
“再回头笔直下切,然后回头以另一个45度角方向向上切割,再回头笔直下切,接着……”
“……直到你完成一个鸠尾榫接头。那便是我刚才所描述的!”
这听起来像不像你曾听说的一次代码评审?在那里程序员这样描述被评审的代码:
接着,我使用一个WHILE循环去做……接着是一系列的IF声明去做……到这里我使用一个SWITCH去处理……
你得到一段代码细节的描述,但是你不知道这个程序究竟在做什么以及为什么这样做!
当然,一个有自尊心的木匠是不会这样讲话的。真正会发生的可能是这样的:
木匠1:我们是使用鸠尾榫接头还是斜面接头?
我们已经看到一个性质上的不同。木匠们讨论的是问题解决方案质量的不同;他们的讨论在一个更高的,更抽象的层次上。他们避免陷身于一个特殊解决方案细节的泥沼之中。
当木匠谈到一个斜面接头时,他或她头脑中的方案有着以下的特征:
l 这是一个简单的方案——斜面接头制造起来很简单。你用45度角切割连接块的边缘,将它们邻接,然后将它们用钉子钉在一起或者用胶水粘合在一起。(如图5-2)
l 它是轻量级的——斜面接头不如鸠尾榫接头牢固。它不能承受巨大的压力。
l 它是不显眼的——相较于鸠尾榫接头的多切割,斜面接头的单切割很不引人注意。
图5-2一个斜面接头
当木匠谈论到鸠尾榫接头(我们在第81页描述过如何制造)时,他或她脑中的方案则有着另外一些特征。或许对外行来说,这些特征并不明显,但是对任何木匠来说,它们都是清楚明白的。
l 它是一个更复杂的方案——制造一个鸠尾榫接头更加棘手,因此也便更加昂贵。
l 它不受温度和湿度的影响——在这些条件发生变化时,木头会相应地伸缩。然而,鸠尾榫接头将会坚固依旧。
l 它不依赖于紧固系统——事实上,鸠尾榫接头甚至不依赖胶水就可以工作。
l 它是一个更加美观的接头——做得好的话,它看起来很漂亮。
换句话说,鸠尾榫接头是一个牢固、独立、美观的接头,它做起来也就复杂(因此也便昂贵)一些。
因此,当木匠1问道,
我们是使用一个鸠尾榫接头还是用一个斜面接头呢?
真正提出的问题是,
我们是用一个制造昂贵但美观耐用的接头,还是仅仅做一个快捷简陋、只需坚持到检验结束的接头?
我们可以说木匠的讨论事实上是发生在两个层面:言语的表面层,以及真实的谈话,后者发生在一个更高的层次(a meta-level),它将外行隔离开来并且含意丰富的多。这个更高的层面是“木匠模式”层面,它反映了木匠们的真实设计问题。
在第一个案例中,木匠2因为讨论接头的实现细节而将真实问题弄得晦涩不明。在第二个案例中,木匠1想要基于成本和质量来决定使用哪一个接头。
谁更有效率呢?你更愿意和谁一起工作呢?
这就是当我说模式能帮助提高你的思想层次时的含义之一。在本书后面你会看到,当你像这样提高你的思想层次时,新的设计方法将会变得触手可及。这便是模式的真实威力之所在。
学习设计模式的其它好处随着开发组对设计模式的使用,我的经验是设计模式有助于个人学习和团队开发。这是因为团队中的新手看到那些熟悉设计模式的资深开发人员拥有一些有价值的东西,他们也想得到它。这为他们提供动力去学习一些这样的强有力的观念。
大多数设计模式同时使得软件更加容易修改。这是因为它们是经受时间检验的解决方案。因此,相较于那些经常一开始就想出的方案,它们已经发展为能够更加容易处理变化的结构。
如果传授得当,设计模式能够用于大幅地提高对面向对象设计基本原则的理解。在我所教授的介绍性面向对象课程上,这样的事情我见过无数次。在这些课堂上,我以一个简短的面向对象范式介绍开始。接着我便开始传授设计模式,用它们去说明基本的面向对象观念(封装、继承和多态)。虽然我们大部分时间一直在谈论模式,但在三天的课程结束前,这些观念——我们刚刚介绍给很多参与者的观念,让人感觉它们就像老朋友一样。
对于创建好的面向对象设计,四人团建议了好几个策略。以下几条是他们所特别建议地:
l 基于接口设计。
l 优先使用组合,而不是继承。
l 寻找变化并将它封装。
这些策略在本书所讨论的大多数设计模式中被使用。即便你并不了解很多设计模式,学习一些将会使你得知这些策略为什么有用。有了那样的理解,即使你并不直接使用设计模式,你也拥有了将它们应用在你自己的设计问题中的能力,
另外一个好处是设计模式允许你或你的团队为复杂的问题创建设计,而不需要大的继承层次。同样,即使设计模式并没有被直接使用,避免大的继承层次也会导致改良的设计。
总结在本章,我描述了什么是设计模式。Christopher Alexander说“模式是一个背景下的一个问题的解决方案。”它们不仅仅是解决个人问题的一种模板。They are a way of describing the motivations by including both what we want to have happen along with the problems that are plaguing us.
我还查看了学习设计模式的原因。这样的学习有助于
l 复用那些通常一再出现的问题的现有的、高质量的解决方案。
l 建立公共的术语表以改善团队内部的交流。
l 将思想层次转换到一个更高的视角。
l 判定我是否拥有一个正确的设计,而不仅仅是一个能用的设计。
l 提高个人学习和团队学习。
l 改善代码的可修改性。
l 帮助采用改良的设计抉择,即便在模式没有被明确使用的时候。
l 发现大继承层次的替代品。
[1] Alexander, C., Ishikawa, S., Silverstein, M.,建筑的永恒之路,纽约:牛津大学出版社,1979。
[2] 在对文化的基于模式的分析方面,人类学者Ruth Benedict是一位先驱。参见Benedict, R., 菊与剑,波士顿:霍顿·密夫林,1946。
[3] Alexander, C., Ishikawa, S., Silverstein, M., 模式语言, 纽约:牛津大学出版社,1977,p. x.
[4] Alexander,C.,Ishikawa,S.,Silverstein,M.,建筑的永恒之路,纽约:牛津大学出版社,1977。
[5] 欧洲的ESPRIT社团在1980年代正进行着类似的工作。ESPRIT的项目1098和项目5248开发了一个基于模式的设计方法,该方法被称作知识分析与设计支持(KADS),它将焦点集中在用于创建专家系统的模式。Karen Gardner将KADS分析模式扩展到面向对象。参见Gardner, K., 认知模式:对象技术的问题解决框架,纽约:剑桥大学出版社,1998。
[6] Gamma,E.,Helm,R.,Johnson,R.,Vlissiders,J.,设计模式:可复用面向对象软件的基础,Reading,Mass:Addison-Wesley,1995。
[7] 谈话的灵感来自Ralph Johnson的一段讲演,并经过作者的改编。
本文地址:http://com.8s8s.com/it/it33021.htm