您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 设计模式:可复用面向对象软件的基础
设计模式:可复用面向对象软件的基础1什么是设计模式ChristopherAlexander说过:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”[AIS+77,第10页]。尽管Alexander所指的是城市和建筑模式,但他的思想也同样适用于面向对象设计模式,只是在面向对象的解决方案里,我们用对象和接口代替了墙壁和门窗。两类模式的核心都在于提供了相关问题的解决方案。一般而言,一个模式有四个基本要素:1.模式名称(patternname)一个助记名,它用一两个词来描述模式的问题、解决方案和效果。命名一个新的模式增加了我们的设计词汇。设计模式允许我们在较高的抽象层次上进行设计。基于一个模式词汇表,我们自己以及同事之间就可以讨论模式并在编写文档时使用它们。模式名可以帮助我们思考,便于我们与其他人交流设计思想及设计结果。找到恰当的模式名也是我们设计模式编目工作的难点之一。2.问题(problem)描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。也可能描述了导致不灵活设计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。3.解决方案(solution)描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题。4.效果(consequences)描述了模式应用的效果及使用模式应权衡的问题。尽管我们描述设计决策时,并不总提到模式效果,但它们对于评价设计选择和理解使用模式的代价及好处具有重要意义。软件效果大多关注对时间和空间的衡量,它们也表述了语言和实现问题。因为复用是面向对象设计的要素之一,所以模式效果包括它对系统的灵活性、扩充性或可移植性的影响,显式地列出这些效果对理解和评价这些模式很有帮助。出发点的不同会产生对什么是模式和什么不是模式的理解不同。一个人的模式对另一个人来说可能只是基本构造部件。本书中我们将在一定的抽象层次上讨论模式。《设计模式》并不描述链表和hash表那样的设计,尽管它们可以用类来封装,也可复用;也不包括那些复杂的、特定领域内的对整个应用或子系统的设计。本书中的设计模式是对被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述。一个设计模式命名、抽象和确定了一个通用设计结构的主要方面,这些设计结构能被用来构造可复用的面向对象设计。设计模式确定了所包含的类和实例,它们的角色、协作方式以及职责分配。每一个设计模式都集中于一个特定的面向对象设计问题或设计要点,描述了什么时候使用它,在另一些设计约束条件下是否还能使用,以及使用的效果和如何取舍。既然我们最终要实现设计,设计模式还提供了C++和Smalltalk示例代码来阐明其实现。虽然设计模式描述的是面向对象设计,但它们都基于实际的解决方案,这些方案的实现语言是Smalltalk和C++等主流面向对象编程语言,而不是过程式语言(Pascal、C、Ada)或更具动态特性的面向对象语言(CLOS、Dylan、Self)。我们从实用角度出发选择了Smalltalk和C++,因为在这些语言的使用上,我们积累了许多经验,况且它们也变得越来越流行。程序设计语言的选择非常重要,它将影响人们理解问题的出发点。我们的设计模式采用了Smalltalk和C++层的语言特性,这个选择实际上决定了哪些机制可以方便地实现,而哪些则不能。若我们采用过程式语言,可能就要包括诸如“继承”、“封装”和“多态”的设计模式。相应地,一些特殊的面向对象语言可以直接支持我们的某些模式,例如:CLOS支持多方法(multi-method)概念,这就减少了Visitor模式的必要性。事实上,Smalltalk和C++已有足够的差别来说明对某些模式一种语言比另一种语言表述起来更容易一些(参见5.4节Iterator模式)。2SmalltalkMVC中的设计模式在Smalltalk-80中,类的模型/视图/控制器(Model/View/Controller)三元组(MVC)被用来构建用户界面。透过MVC来看设计模式将帮助我们理解“模式”这一术语的含义。MVC包括三类对象。模型Model是应用对象,视图View是它在屏幕上的表示,控制器Controller定义用户界面对用户输入的响应方式。不使用MVC,用户界面设计往往将这些对象混在一起,而MVC则将它们分离以提高灵活性和复用性。MVC通过建立一个“订购/通知”协议来分离视图和模型。视图必须保证它的显示正确地反映了模型的状态。一旦模型的数据发生变化,模型将通知有关的视图,每个视图相应地得到刷新自己的机会。这种方法可以让你为一个模型提供不同的多个视图表现形式,也能够为一个模型创建新的视图而无须重写模型。下图显示了一个模型和三个视图(为了简单起见我们省略了控制器)。模型包含一些数据值,视图通过电子表格、柱状图、饼图这些不同的方式来显示这些数据。当模型的数据发生变化时,模型就通知它的视图,而视图将与模型通信以访问这些数据值。表面上看,这个例子反映了将视图和模型分离的设计,然而这个设计还可用于解决更一般的问题:将对象分离,使得一个对象的改变能够影响另一些对象,而这个对象并不需要知道那些被影响的对象的细节。这个更一般的设计被描述成Observer(5.7)模式。MVC的另一个特征是视图可以嵌套。例如,按钮控制面板可以用一个嵌套了按钮的复杂视图来实现。对象查看器的用户界面可由嵌套的视图构成,这些视图又可复用于调试器。MVC用View类的子类—CompositeView类来支持嵌套视图。CompositeView类的对象行为上类似于View类对象,一个组合视图可用于任何视图可用的地方,但是它包含并管理嵌套视图。上例反映了可以将组合视图与其构件平等对待的设计,同样地,该设计也适用于更一般的问题:将一些对象划为一组,并将该组对象当作一个对象来使用。这个设计被描述为Composite(4.3)模式,该模式允许你创建一个类层次结构,一些子类定义了原子对象(如Button)而其他类定义了组合对象(CompositeView),这些组合对象是由原子对象组合而成的更复杂的对象。MVC允许你在不改变视图外观的情况下改变视图对用户输入的响应方式。例如,你可能希望改变视图对键盘的响应方式,或希望使用弹出菜单而不是原来的命令键方式。MVC将响应机制封装在Controller对象中。存在着一个Controller的类层次结构,使得可以方便地对原有Controller做适当改变而创建新的Controller。View使用Controller子类的实例来实现一个特定的响应策略。要实现不同的响应策略只要用不同种类的Controller实例替换即可。甚至可以在运行时刻通过改变View的Controller来改变View对用户输入的响应方式。例如,一个View可以被禁止接收任何输入,只需给它一个忽略输入事件的Controller。View-Controller关系是Strategy(5.9)模式的一个例子。一个策略是一个表述算法的对象。当你想静态或动态地替换一个算法,或你有很多不同的算法,或算法中包含你想封装的复杂数据结构,这时策略模式是非常有用的。MVC还使用了其他的设计模式,如:用来指定视图缺省控制器的FactoryMethod(3.3)和用来增加视图滚动的Decorator(4.4)。但是MVC的主要关系还是由Observer、Composite和Strategy三个设计模式给出的。3描述设计模式我们怎样描述设计模式呢?图形符号虽然很重要也很有用,却还远远不够,它们只是将设计过程的结果简单记录为类和对象之间的关系。为了达到设计复用,我们必须同时记录设计产生的决定过程、选择过程和权衡过程。具体的例子也是很重要的,它们让你看到实际的设计。我们将用统一的格式描述设计模式,每一个模式根据以下的模板被分成若干部分。模板具有统一的信息描述结构,有助于你更容易地学习、比较和使用设计模式。模式名和分类模式名简洁地描述了模式的本质。一个好的名字非常重要,因为它将成为你的设计词汇表中的一部分。模式的分类反映了我们将在1.5节介绍的方案。意图是回答下列问题的简单陈述:设计模式是做什么的?它的基本原理和意图是什么?它解决的是什么样的特定设计问题?别名模式的其他名称。动机用以说明一个设计问题以及如何用模式中的类、对象来解决该问题的特定情景。该情景会帮助你理解随后对模式更抽象的描述。适用性什么情况下可以使用该设计模式?该模式可用来改进哪些不良设计?你怎样识别这些情况?结构采用基于对象建模技术(OMT)[RBP+91]的表示法对模式中的类进行图形描述。我们也使用了交互图[JCJO92,BOO94]来说明对象之间的请求序列和协作关系。附录B详细描述了这些表示法。参与者指设计模式中的类和/或对象以及它们各自的职责。协作模式的参与者怎样协作以实现它们的职责。效果模式怎样支持它的目标?使用模式的效果和所需做的权衡取舍?系统结构的哪些方面可以独立改变?实现实现模式时需要知道的一些提示、技术要点及应避免的缺陷,以及是否存在某些特定于实现语言的问题。代码示例用来说明怎样用C++或Smalltalk实现该模式的代码片段。已知应用实际系统中发现的模式的例子。每个模式至少包括了两个不同领域的实例。相关模式与这个模式紧密相关的模式有哪些?其间重要的不同之处是什么?这个模式应与哪些其他模式一起使用?附录提供的背景资料将帮助你理解模式以及关于模式的讨论。附录A给出了我们使用的术语列表。前面已经提到过的附录B则给出了各种表示法,我们也会在以后的讨论中简单介绍它们。最后,附录C给出了我们在例子中使用的各基本类的源代码。4组织编目设计模式在粒度和抽象层次上各不相同。由于存在众多的设计模式,我们希望用一种方式将它们组织起来。这一节将对设计模式进行分类以便于我们对各族相关的模式进行引用。分类有助于更快地学习目录中的模式,且对发现新的模式也有指导作用。我们根据两条准则对模式进行分类。第一是目的准则,即模式是用来完成什么工作的。模式依据其目的可分为创建型(Creational)、结构型(Structural)、或行为型(Behavioral)三种。创建型模式与对象的创建有关;结构型模式处理类或对象的组合;行为型模式对类或对象怎样交互和怎样分配职责进行描述。第二是范围准则,指定模式主要是用于类还是用于对象。类模式处理类和子类之间的关系,这些关系通过继承建立,是静态的,在编译时刻便确定下来了。对象模式处理对象间的关系,这些关系在运行时刻是可以变化的,更具动态性。从某种意义上来说,几乎所有模式都使用继承机制,所以“类模式”只指那些集中于处理类间关系的模式,而大部分模式都属于对象模式的范畴。创建型类模式将对象的部分创建工作延迟到子类,而创建型对象模式则将它延迟到另一个对象中。结构型类模式使用继承机制来组合类,而结构型对象模式则描述了对象的组装方式。行为型类模式使用继承描述算法和控制流,而行为型对象模式则描述一组对象怎样协作完成单个对象所无法完成的任务。还有其他组织模式的方式。有些模式经常会被绑在一起使用,例如,Composite常和Iterator或Visitor一起使用;有些模式是可替代的,例如,Prototype常用来替代AbstractFactory;有些模式尽管使用意图不同,但产生的设计结果是很相似的,例如,Composite和Decorator的结构图是相似的。还有一种方式是根据模式的“相关模式”部分所描述的它们怎样互相引用来组织设计模式。图1-1给出了模式关系的图形说明。显然,存在着许多组织设计模式的方法。从多角度去思考模式有助于对它们的功能、差异和应用场合的更深入理解。
本文标题:设计模式:可复用面向对象软件的基础
链接地址:https://www.777doc.com/doc-4398507 .html