GRASP:基于职责设计对象
目标:
- 学习使用面向对象设计的5个GRASP原则或模式
本章和下一章对理解面向对象设计的核心内容有重大意义。有时候,OOD会被解释为:
首先明确你的需求并创建领域模型,然后为适当的类添加方法,再定义对象之间的消息以实现需求。
如此含糊的建议对我们没有任何帮助,因为其中涉及一些深奥的原则和问题。决定方法归属于那个对象和对象之间如何交互,其意义重大,应谨慎从事。掌握OOD涉及一套柔性原则,自由度很大,这正式OOD的复杂所在。但OOD并不是魔术,其模式时可以命名、解释和应用的。例子可以蚌湖我们,实践可以帮助我们。下面这个小的办法也可以帮助我们:对案例进行研究之后,试着与同事们一起,在墙上重新创建Monopoly的解决方案,并运用这些原则,如信息专家。
UML与设计原则
由于UML只是一种标准的、可视化建模语言,了解它的细节并不能教会你如何用对象思想来思考,而对象思想正是本书的主题。UML有时候被描述成一种“设计工具”,但是这并不完全正确.最关键的软件开发工具是受过良好设计原则训练的思维,而不是UML或任何其他技术。
对象设计:输入、活动和输出示例
本节概述了以迭代方法设计的示例全景:
- 已经完成了哪些活动?--以前的活动和制品。
- 事物之间具有什么样的关系?--以前的制品对OO设计的影响。
- 需要完成多少设计建模工作,如何完成?
- 有哪些输出? 特别是,希望你能理解分析制品与对相信设计之间的关系。

对象设计的输入是什么
让我们从过程输入开始,假定我们是NextGen POS项目的开发者,并且以下场景是真实的:
| 第一个为期两天的需求讨论会已经完成。 | 总架构师和业务人员已统一在第一个为期三周的时间定量迭代中实现和测试某些处理销售用例的场景。 | | 已经详细分析了架构上最重要的业务和业务价值最高的20个中立中的3个用例,其中包括处理销售用例(UP所建议的典型迭代方法是,开始编程之前仅详细分析10%到20%的续期)。 | 其他制品已经启动,包括补充规格说明、术语表和领域模型 | | 编程实验已经解决“演示阻塞”的技术问题,如在触摸屏上Java Swing UI 是否起作用 | 总架构师已经利用UML包图提出了大型逻辑架构的构思。这是UP设计模型的一部分 |
需要输入哪些制品,他们与对象设计有什么样的关系?
| 用例文本定义最终必须得到软件对象的支持(对象必须能够实现用例)的可是行为。在UP中,这种OO设计也被顺理成章地称为用例实现 | 补充规格说定义了非功能性的目标,例如国际化,我们的对象必须满足这些目标。 | | 系统顺序图确定系统操作消息,它是合作对象交互图中的开始消息。 | 词汇表明确来自UI层的参数或数据、传递到数据库的数据的细节,已经详细的特定项逻辑或验证需求、如合肥的格式和对产品UPC的有效性验证。 | | 操作锲约用来补充用例文本,已明确在系统操作中软件对象必须完成什么任务。后置条件定义了系统操作的详细结果。 | 领域模型描述了软件架构的领域层软件领域对象的名称和属性 |
这些视频不一定都是必要的。记住,在UP中所有元素都是可选的,也许是为了降低某种风险而创造的。
对象设计中的活动
现在,准备告别分析师的身份而开始设计者和建模者的工作。
给定一个或多个输入,开发者有以下三个选择:
- 立即开始编码(理想的情况是用测试优先开发方式)。
- 开始为对象设计进行一些UML建模。
- 利用其他建模技术。
在UML案例中,真正要关注的并不是UML,二十可视化建模,即使用一种语言,这种语言比纯文本有更强的可视化功能。更为重要的是,在绘图活动当中,我们要运用各种OO设计原则。OO色痕迹建模总的来说,基于职责驱动设计所代表的内在含义是考虑怎么样给写作中的对象分配至职责。
本章和后续几章将探讨应用RDD、GRASP已经某些GOF设计模式的含义。
在建模日中,团队可能需要分成几个小组,工作2-6个小时,通过在墙上勾图,或利用软件建模工具,来为设计中具有创造性、最苦难的部分建模。其中包括UML图、原型工具、草图等来完成UI、OO和数据库的建模。
在绘制UML图期间,我们采取现实的态度,即我们绘制模型主要是为了理解和沟通,并不是为了编写文档。当然,我们期望通过某些UML图能顺利生成代码。
在为期三周的时间定量迭代在前期,开发团队停止建模,开始程序员的工作,已避免在编程之前过度建模。
有哪些输出
在设计期间我们可能会提到这些输入的分析,例如重新阅读用例文本或操作契约,浏览领域模型并评审补充规格说明。
在建模日创建了什么?
- 尤其对于对象设计而言,我们期望在开始编码之前针对设计中难点创建UML教徒图、类图和包图。
- UI的草图和原型。
- 数控模型
- 报表的草图和原型。
职责和职责驱动设计
思考软件兑现该设计以及大型构件的流行凡是是,考虑其职责、角色和协作。这是被称为制作驱动设计的大型方法的一部分。
在RDD中,我们认为软件对象具有职责,即对其所作所为的抽象。UML把职责定义为“类元的契约或义务”。就对象的角色而言,职责与对象的义务和行为相关。职责分为以下两种类型:行为和认知。
对象的行为职责包括:
- 自身执行一些行为,如创建对象或计算。
- 初始化其他对象中的动作。
- 控制和协调其他对象中的活动。 对象的认知职责包括:
- 对私有封装数据的认知。
- 对相关对象的认知。
- 对其能够导出或计算的事物的认知。
在对象设计中,职责被分配给对象类。
准则:对于软件领域对象来说,由于领域模型描述了领域对象的属性和关联,因此其通常产生于“认知”相关的职责。
纸质的粒度会影响职责到类和方法的转换。大力度职责具有数百个类和方法。小翟路职责可能只是一个方法。
职责于方法并非同一事物,职责是一种抽象,而方法实现了职责。
RDD也包括了协作的思想,职责借助于方法来事变,该方法既可以单独动作,也可以于其他方法和对象协作。
RDD是思考OO软件设计的一般性隐喻。把软件对象想象成具有某种职责的人,他要与其他人协作以完成工作。RDD使我们把OO设计看作使有职责对象进行协作的共同体。
关键点:GRASP对一些基本的职责分配原则进行了命名和描述,因此掌握这些原则有助于支持RDD。
GRASP:基本OO设计的系统方法
GRASP:使用职责进行OO设计的学习工具
掌握基本对象设计和职责分配需要详细的原则和退了,对这些原则和推理进行命名和解释使可能的。GRASP原则或模式使一种学习工具,它能帮助你理解基本对象设计,并且以一种系统的、合理的、可以解释的方式来运用设计推理。对这种设计院进行理解和使用的基础使分配职责的模式。
理解在对象设计中如何运用GRASP使本书的一个关键目标。
所以GRASP使有重要意义的,但另一方面,它只是对原则及逆行结构化和命名的一种学习工具。一般你掌握了这些基本原则,特定的GRASP术语就不重要了。
职责、GRASP和UML图之间的关系
你可以想一想,在编写代码或建模时,如何给对象分配职责。在UML之中,绘制交互图时考虑这些职责的时机。
因此,当我们在绘制UML交互图时,就是在决定职责的分配。本章着重强调GRASP中的基本原则,以指导在分配职责时可做的选择。这样,当绘制UML交互图以及编写代码时,你就可以运用GRASP原则了。
什么时模式
有经验的OO开发者建立了既有通用原子又有惯用方案的指令系统来指导他们编制软件。如果以结构化形式对这些问题、解决方案和命名进行描述使其系统化,那么这些原则和习惯用法就可以称为模式。
在OO设计中,模式时对问题和解决方案的已命名描述,它可以哟关于新的语境。理想情况下,模式在为变化缓解中如何运用和权衡其解决方案给出建议。对于特定问题,可以用用许多模式为对象分配职责。
简单的讲,好的模式是成对的问题/解决方案,并且具有广为人知的名称,它能用于新的语境中,同时对新情况下的应用、权衡、实现、变化等给出了建议。
模式具有名称--重要!
软件开发是一个年轻领域。年轻领域中的原则缺乏大家广泛认可的名称,这为沟通和培训带来了苦难。模式具有名称,。对模式、设计思想或原则命名具有以下好处:
- 它支持讲概念条理化地组织为我们的理解和记忆。
- 它便于沟通 模式被命名并且广泛发布后,我们就可以在讨论复杂设计思想时使用简语,这可以发挥抽象的优势。
“新模式”时一种矛盾修饰符
新模式如果米奥数的时新思想,则应当被认为时一种矛盾修饰法。术语“模式”的真实含义时长期重复的事物。设计模式要点闭关不是要表达新的设计思想。恰恰相反,优秀模式的意图时讲已有的经过验证的只是、官方发和原则汇编起来;磨砺的越多、越悠久、使用的越广泛,这样的模式就越优秀。
因此,GRASP模式陈述的并不是新思想,他们只是讲广泛使用的基本原则命名并汇总起来。对于OO设计专家而言,GRASP模式应作为其基础和熟练掌握的原则。
GOR关于设计模式的著作
学习GRASP和基本GoF模式时本书的关键目标。
GRASP是一组模式或原则吗
GRASP定义了9个基本OO设计原则或基本设计构件。有些人会问, “难道GRASP描述的时原则而不是模式吗?”,设计模式一书的序言给出了答案:某人的模式时其他人的原始构造块。
本书并不注重模式的表示和描述,而更光柱模式的实用价值,即模式时一种优秀的学习工具,可以用来命名、表示和记忆那些安歇基本和经典的设计思想。
现在我们所处的位置
至此,本章已经概述了OO设计的背景:
- 迭代过程背景-有哪些优先制品?他们与OO设计模型有什么关系?我们应答花费多少时间进行设计建模?
- 作为对象设计隐喻的RDD:有职责对象协作的共同体。
- 作为OO设计思想命名和解释方式的模式:分配职责的基本哦是时GRASP,对于更为高级的设计思想则应用GOF模式。模式可在建模期间和编码期间应用。
- UML用于OO设计的可视建模,再次期间,GRASP和GoF模式都能使用。
使用GRASP进行对象设计的简短示例
以下几节架构详细探讨GRASP,不过我们还是从一个简短的例子开始,了解用于Monooly案例研究的重要思想。共有9个GRASP模式,本案例之应用了以下几个:
- 创建者
- 信息专家
- 低耦合
- 控制器
- 高内聚
创建者
问题:由谁创建Square对象?
在OO设计中,你必须考虑的首要问题之一时:由谁创建对象X?这是行为职责。例如,在Monopoly案例研究中,由谁来创建Square对象呢?既然目前任何对象都可以创建Square,那么对于众多OO开发者而言,他们的选择应该是什么?为什么?
是否可以用Dog对象(也就是某个任意的类)作为创建者?不行!我们可以确信这一点。为什么?业务它不会出现在我们想象中的领域模型,这是关键点。在我们对领域的思考与直接对应的软件对象之间,Dog不支持低表示差异。我曾经就字面意义与数千个开发者探讨过这个问题,实际上从印度到每个,每个开发者都会说“用Borad对象来创建Square”。十分尤其!者反映了一种“直觉”,OO软件开发者常常想让“容器”创建被“容纳”的事物,就像Board创建Square一样。
顺便说一下,我们之所以用Square和Board这样的名称来定义软件类,而不用AB324和ZC17是根据LRG决定的。它把UP领域模型和UP设计模型联系起来,或者是把我们想象的领域模型与软件架构领域层中与之响应的实现联系起来。
以此为背景,这里给出创建者模式的定义:
- 名称:创建者
- 问题:谁创建了A?
- 解决方案:如果以下条件之一为真时(越多越好),讲创建类A示例的职责分配给类B:
- B “包含”或组成聚集了A。
- B 记录A。
- B 紧密地使用A。
- B 具有A的初始化数据。
注意,这必须和职责的分配联系起来。让我们看看如何应用创建者模式。
首先,在应用创建者和其他GRASP模式时,又一个虽小但很重要的问题:B和A指的时软对象,而不是领域模型对象。我们先试着通过寻找满足B角色的现有软件对象来应用创建者。但是如果我们只是杠开始OO设计,还没有定义软件类,那该怎么办呢?在此案例中,依靠LRG,来从领域模型中获得灵感。
因此,对于创建Square的问题,由于还没有定义软件类,我们穿领域模型,会发现Board包含Square。这是概念上的看法,但不是软件的看法。当然我们可以在设计模型里反映这种看法,时Board软件对象包含Square软件对象。根据LRG和创建者的建立,Board讲创建Square。并且Square将永远时Board的一部分,Board控制Square的创建和标会,Square与Board具有组成聚合关联。
回顾以下,敏捷建模实践时并行和互补地创建动态和静态对象模型的。因此,我同时绘制了局部顺序图和类图已反映该设计决策,其中在绘制UML图时我运用了GRASP模式。
信息专家
问题:如果给定键值,谁指导Square对象的相关信息?
在对象设计中,信息专家模式时最基本的职责分配原则之一。
假设对象应该能够引用指定了名称的特定Square。那么对于指定键值,谁应该负责了解Square?当然,这是认知职责,但是专家也适用于行为职责。
和创建者一样,任何对象都可以对此复杂,但是对于众多OO开发者而言,他们会选择什么?为什么?与创建者问题一样,大多数OO开发者会选择Board对象。把该职责分配给Board似乎时显而易见的,但时这里例子可以解释其中的道理,学习该案例有助于在更复杂情况下应用该原则。后续的例子将更为复杂。
信息专家解释了为什么要选择Board:
- 名称:信息专家
- 问题:给对象分配职责的基本原则时什么?
- 解决方案:把职责分配给具有完成该职责所需信息的那个类。
职责需要履行职责的信息,即关于其他对象的信息,对象自身的状态、对象周围的缓解、对象能够导出的信息等等。在本例中,为了能够检索和表示任何Square,某个对象必须知道所有Square。前面以及给出决策,软件Board将聚集所有Square对象。因此,Board具有旅行此职责所必须的信息。
低耦合
问题:为什么时Board而不是Dog?
专家指导我们,由于Board了解所有Qauare,所以将获知特定Square的职责分配给Board对象,但是为什么专家模式各处这样的建议?
可在低耦合原则中找到这个问题的答案。简要地说,耦合时元素与其他元素的连接、感知及依赖的程度的度量。如果存在耦合或依赖,那么当被依赖的元素发生变化时,则依赖着也会收到影响。调用对象B的操作的对象A与对象B的服务之间具有耦合作用。
低耦合原则适用于软件开发的许多方面,它实际上是构件软件最重要的目标之一。就对象设计和职责而言,我们可以像下面这样描述该建议:
- 名称低耦合
- 问题:如何减少因变化产生的影响?
- 解决方案:分配职责以便耦合保持在较低的谁。用该原则可对可选方案纪念性评估。
我们用低耦合原则来评价现有设计,或者评价在新的可选方案之间做出的选择,我们应该首选耦合耕地的设计。
对于这个不太好的Dog设计与我们起初阿哥由Board来完成getSquare的设计,我们来评价以下、、一下总体耦合性。
更高的目标层次上考虑,为什么期望低耦合呢?换言之,为什么我们要减少变化产生的影响呢?因为低耦合往往能够减少修改软件所需的时间、工作量和缺陷。这只是个简要的回答,但是它对于构建和维护软件而言具有重大意义。
回到信息专家的动机:该原则可以指导我们做出之hi低耦合的选择。专家让我们寻找这样的对象,该对象具有职责所需的大部分信息,并把职责分配给该对象。
如果我们把职责分配到其他地方,那么总体耦合会比较高,因为存在更多的信息或对象必须被某些事物所分享,而这些事物源系信息有和对象的本院。
控制器
简单的分层架构包括UI层和领域层等。参与者产生UI事件。UI软件对象必须对鼠标标记事件做出反映,使游戏能够玩起来。
根据MVS原则,我们指导UI对象不应当包含应用漏极和业务逻辑。因此,一旦UI对象获得了此鼠标事件,他们应该把该请求我拍给领域层的领域对象。
控制器模式回答这样一个简单问题:在UI层之上的哪个对象应该首先从UI层接收该消息呢?
你明变SSD系统操作和从UI层到领域层的详细对象设计之间的联系吗?这是重要的。
因此,控制器处理OO设计中的基本问题:怎样将UI层连接到和应用逻辑层?从UI层接受playGame消息的第一个对象对Board吗?或者使其他对象?
在一些OOA/D方法中,控制器使对应用逻辑对象的米高梅,它接收亲贵并控制对请求的处理。
控制器模式提供下面的建议:
- 名称:控制器
- 问题:在UI层之上首先接收和协调系统操作的对象使什么?
- 解决方案:把职责分配给能代表下列选择之一的对象:
- 代表全部“系统”、“跟对象”、运行软件的设备或主要的子系统。
- 代表发生系统操作的用例场景。
让我们考虑一下选项:
- 代币哦全部“系统”或根对象,例如MonopolyGame对象。
- 代表运行软件的设备,这个选项术语特定硬件装置,如电话机或银行兑钞机,该选项不适用于本例。
- 代表用例或会话。法伤playGame系统操作的用例称为玩Monopoly游戏。因此,向PlayMonopolyGamehander 这样的软件类。
如果只有少数几个系统操作,选择选项#1使比较合理的。
高内聚
内聚使软件设计中的一种基本品质,内聚可以非正式地用于度量软件元素操作在功能上的相关程度,也用于度量软件元素完成的工作量。看下面两个例子作为对象。有100个方法和200行源代码的Big对象,要比只有10个方法和200行代码的Small对象所完成的任务多很多。如果Big对象的100个方法覆盖率众多不同的职责领域,那么Big对象那个比Small对象的功能内聚性更低。概括地讲,代码的熟练及其相关性都是对象内聚程度的指示器。
很明显,不灵内聚不只是意味着对象仅依靠本身工作;实际上,具有2000行源代码的低内聚对象或许需要和大量其他对象进行协作。所有的交互也都会趋于产后不俩个耦合。不良内聚和不良耦合通常使起头并进的。
- 名称:高内聚
- 问题:怎样使对象保持由内聚、可理解和可管理,同时具有支持低耦合的附加作用?
- 解决方案:职责分配应保持高内聚,依次来评估备选方案。
在对象设计中应用GRASP
GRASP使通用职责分配软件模式的缩写。之所以选择这个名称,是为了表明掌握这些原则对于成功设计面向对象软件的重要性。
对象技术初学者在编码或绘制交互图和类图时应该理解并应用GRASP的基本思想,以便尽快地掌握这些基本原则,他们时设计OO系统的基础。
GRASP的9个模式如下所示:
- 创建者
- 信息专家
- 低耦合
- 控制器
- 高内聚
- 多态性
- 纯虚构
- 间接性
- 防止变异。
创建者
问题
谁应该复杂创建某类的新实例?
创建对象是面向对象系统中最常见的活动之一。因此,应该有一些通用的原则用于创建职责的分配。如果分配的好,设计就能够支持低耦合,提高清晰度、封装性和可复用性。
解决方案
- 解决方案:如果一下的条件之一为真时,讲传教类A实例的职责分配给类B。
- B “包含”或组成聚集A。
- B 记录A。
- B 直接使用A。
- B 具有A的初始化数据,并且在创建A时会将这些数据传递给A。因此对于A的传教而言,B时专家。
B是对象A的创建者。
如果有一个以上的选项使用,通常首选聚集或包含A的类B。
讨论
创建者模式指导我们分配哪些与创建对象有关的职责。创建者模式的基本意图是需闹在任何情况下都与被创建对象具有连接的创建者。如此选择是为了保持低耦合。
组合聚集部分,容器容纳内容,记录着进行记录,所有这些都是类图中类之间极为常见的关系。创建者模式建议,封装的容器或记录器类是创建其所容纳或记录的事物的很好的候选者。
我们在考虑创建者模式时提到了组合的概念。组合对象时创建其组成部分的良好候选者。
有时,可以勇敢寻找具有初始化数据的类来确定创建者,这些数据讲在创建过程中传递给被创建者。这实际上就是专家模式的例子。初始化数据在创建期间时通过某种初始化方法来传递的。
禁忌
对象的创建常常具有相当的复杂性,在这些情况下,最好的方法时把创建职责委派给成为i具体工程或抽象工程的辅助类,而不是使用传几张模式所建议的类。
优点
- 支持低耦合,这意味着它具有较低的维护依赖性和较高的复用性。这种方法可能不会增加耦合性,业务其所创建的类对于床之类而言以及时可见的,正式由于存在已有的管理,一次它成为i创建者。
向模式或原则
- 低耦合
- 具体工程和抽象工程
- 整体-部分描述了定义聚合对象的模式,它支持对构建的封装。
信息专家(或专家)
问题
给对象分配职责的基本原则时什么?
一个设计模型也许要定义数百或数千个软件类,一个应用程序也许需要实现数百或数千个职责。在对象设计中,当定义好对象之间的交互后,我们就可以对软件类的职责分配做出选择。如果选择得好,系统就会易于理解、维护和扩展,而我们的选择也能为未来的应用提供更多服用构建的机会。
解决方案
把职责分配给信息专家,它具有实现这个职责所必须的信息
讨论
信息专家经常用于职责分配,这是对象设计中不断使用的基本指导原则。专家并不意味着模糊或奇特的相反,它表达了一种“直觉”,及对象完成与其所具有的信息给i昂贵的职责。
注意,完成职责往往需要分布在不同对象类中的信息。这意味着需要多“局部”的信息专家要通过协作来完成任务。只要信息分布在不同对象上,对象就需要通过消息进行交互来共同完成工作。
专家模式通常导致这样一种设计,软件对象所作的操作通常时作用域它们在真实世界中所代表的非生命体的哪些操作。
信息专家模式是对真实世界的模拟。我们一般把职责分配给那些具有完成任务所必须的信息的个体。
禁忌
某些情况下,专家模式的方案也许并不何时,通常这是由于耦合与内聚问题所产生的。
优点
- 因为对象使用自身信息来完成任务,所以信息的封装性得以维持。这样就支持了低耦合,进而形成更为健壮的、可维护的系统。
- 行为分布在哪些具有所需信息的类之间,因此提倡定义内聚性更浅的“轻量级”的类,这样易于理解和维护。
相关模式或原则
- 低耦合
- 高内聚
也称为:类似于
- “把职责与数据置于一处”
- “知其则,行其事”
- “DIY”
- “把五福于其属性置于一处”
低耦合
问题
怎样降低依赖线,减少变化嗲来的影响,提高重用性?
耦合是对某元素与其他元素之间的连接、感知和依赖程度的度量。具有低耦合的元素不会过度依赖于其他元素;“过度”是与语境相关的,但我们必须对此进行严查。这些元素包括类、子系统、系统等。
具有高耦合的类依赖于许多其他的类,这样的类或许不是我们所需要的。有些类会遇到一下问题:
- 由于相关类的变化而导致本体被迫变化
- 难以单独地理解。
- 由于使用高耦合类时需要它所依赖的类,因此很难重用。
解决方案
分配职责,使耦合性尽可能地。利用这一原则来评估可选方案。
讨论
低耦合是在制定决策期间必须牢记的原则,它是应该不断考虑的基本目标。它是评估所有涉及结果时要运用的评估原则。
在C++、Java和C#这样的面向对象语言中,从TypeX到TypeY耦合的场景形式包括:
- TypeX具有引用TypeY的实例或TypeY自身的属性。
- TypeX对象调用TypeY对象的服务。
- TypeX具有以任何形式应用TypeY的实例或TypeY自身的方法。通常包括类型TypeY的参与或局部变量,或者由消息返回的对象时TypeY的实例。
- TypeX时TypeY的直接胡哦间接子类。
- TypeY是接口,而TypeX是此接口的实现。
低耦合提倡职责分配要避免产生居于负面影响的高耦合。
低耦合支持在设计时降低类的依赖性,这样可以减少变化所带来的影响。低耦合不能脱离专家和高内聚等其他模式孤立地考虑,而应作为影响职责分配的设计原则之一。
子类于其超类之间由很强的耦合性。因为这是一种强耦合形式,所以要仔细地考虑设计超类导出的任何决定。
没有绝对的度量标准来衡量耦合程度的高低。重要的时额能够估测但钱耦合的程度,并估计增加耦合是否会导致问题。一般来说,哪些有着自然继承关系的类和服用程度较高的类,具有较低的耦合性。
低耦合的极端例子时类之间没有耦合。这个例子违反了对象技术的核心隐喻:系统由相互连接的对象构成,对象之间通过消息通信。耦合度过低会产生不良设计,其中会使用一些缺乏内聚性、膨胀、辅助的主动对象来完成所有工作,并且存在大量被动、零耦合的对象来充当简单的数据知识库。对象之间的适度耦合,对于创建i安心对象系统来说时正常必要的,其中的任务时通过被连接的对象之间的协作来完成的
禁忌
高耦合对于稳定和普遍使用的元素而言并不是问题。
高耦合本身并不是问题所在,问题时某些方面不稳定的元素之间的高耦合,这些方面包括接口、实现等。
重要的一点时:作为设计者,我们可以增加林国姓,封装细节和实现,以及在系统众多方面降低耦合的一般性设计。但如果如果我们把经理放到“未来验证”的胡哦没有实际理由的低耦合设计上,则所花费的实际并不值得。
你必须在降低耦合和封装事物之间进行选择,应该关注在实际当中及其不稳定胡哦需要进化的地方。
优点
- 不受其他构件变化的影响
- 易于单独理解
- 便于复用
背景
耦合于内聚时设计中真正的基本原则,应当受到重视,并未所有软件开发者所引用。
相关模式
- 防止变异。
控制器
问题
在UI层之上首先接收和协调系统操作的第一个对象是什么?
在SSD分析期间,要首先探讨系统操作。这些是我们系统的主要输入事件。例如,当使用POS终端的收银员按下“结束销售”按钮时,他就发起了表示“销售以及终止”的系统事件。
控制器是UI层之上的第一个对象,它辅助接收和处理系统操作消息。
解决方案
把职责分配给能代表一下选择之一的类:
- 代表整个“系统”、“跟对象”、运行软件的设备胡哦主要子系统,这些事外观控制器的所有变体。
- 代表用例场景,该场景中发生系统事件,通常命名为
Handler、 Coordinator或 Session。 - 对于统一用例场景的所有系统事件使用相同的控制器类。
- 通俗来说,绘画是与参与者进行交谈的实例。绘画可以具有任意长度,但通常按照用例来组织。
讨论
简言之,这是委托模式。根据理解,UI层不应当包含应用逻辑,所以UI层对象必须把工作请求委托给其他层。当其他才能是领域层时,控制器模式总结了常见选择,作为一个OO开发者,你需要选择作为代表来接收工作请求的领域对象。
系统接收外部输入事件,通常涉及由人操纵的GUI。包括外部消息在内的其他输入媒介有处理呼叫的电信交换机所产生的信号,或在过程控制系统中来自传感器的信息等。
在所有情况下,你必须为这些事件选择一个处理者。求助于控制器模式的指导,可以得到一般情形可接受的、合适的选择。控制器时从UI层进入领域层的一种外观。
通常,你希望对用i的所有系统事件使用相同的控制器类,一边控制器可以维护关于用例状态的信息。不同的控制器可用于不同的惯用例。
控制器设计中的常见缺陷时分配的职责过多。这时,控制器会具有不良内聚,从而违反了高内聚原则。
正常情况下,控制器应当把需要完成的工作委托给其他对象。控制器只是协调或控制这些活动,本身不完成大量的工作。
第一类控制器时表示整个系统、装置或子系统的外观控制器。其思想时选择某个类名,指定其为应用的其他层之上的封面或外观,并且使其提供UI层向其他层调用服务的主要接触点。外观可以时整个物理单元的抽象,也可以时代表整个软件系统的类,也可以时设计者用来表示整个系统或子系统的其他概念。
当没有过多的系统事件,或者用户界面不能把系统事件消息重定向到其他控制器时,选择外观控制器时合适的。
如果你使用用例控制器,那么对于每个用例,应用使用不同的控制器。注意,这种控制器不是领域对象,它时支持系统的人工构造物。
何时应该选择用例控制器?当把职责分配给外观控制器会导致低内聚或高耦合的设计时,通常时当外观控制器的职责过多而变得臃肿时,就需要考虑使用用例控制器。当由跨越不同过程的大量系统事件时,用例控制器也是比较何时的。它可以讲这些系统事件的处理解析为不同的可管理和独立的类,同时能够对感知和推理用例场景当前状态提供基本支持。
在UP中,存在边界类、控制类和实体类的概念。边界对象时接口的抽象,实体对象时与引用无关的领域软件对象,控制对象时此控制器模式描述的用例处理者。
控制器模式的重要结果时,UI对象和UI层不应具有实现系统事件的职责。换句话说,系统操作应当在对象的用用逻辑层或领域层处理,而不是在系统的UI层处理。
优点
- 增加了可复用和接口可拔插的潜力。
- 获得了推测用例状态的机会。
实现
问题和解决方案
相关模式
- 命令:在消息处理系统中,可以用命令对象来表示和处理每个消息。
- 外观:外观控制器时一种外观。
- 层:这是POSA模式。把领域逻辑置于领域层而不是表示层,这是层模式的一部分。
- 纯虚构:这是GRASP模式,其中的软件类时由设计者任意创建的,而不是来源于领域模型。永康控制器时一种纯虚构。
高内聚
问题
怎样保持对象是有重点的、可理解的、可管理的,并且能够支持低耦合。
从对象设计的角度上说,内聚对对元素职责的相关性和集中度的度量。如果元素具有高度相关的职责,而且没有过多巩工作,那么该元素具有高内聚性。这些元素包括类、子系统等等。
解决方案
分配职责可保持较高的内聚性。可利用这一点来评估候选方案。
内聚性较低的类要做许多互补i相关的工作,或需要完成大量的工作。这样的类是不合理的额,它们会导致一下问题:
- 难以理解。
- 难以复用
- 难以维护。
- 脆弱,经常会收到变化的影响。
内聚性低的类通常表示大粒度的抽象,或承担了本应委托给其他对象的职责。
讨论
与低耦合一样,在所有的设计决策期间,高内聚是要时刻牢记的原则,它是一个需要不断考虑的基本原则。它是评估所有涉及决策时,设计者要使用的评价原则。
一下时描述不同功能性内聚程度的一些场景:
- 非常低的内聚。由一个类单独负责完全不同的功能领域中的大量事物。
- 低内聚。由一个类单独辅助一个功能性领域内的复杂任务。
- 高内聚。有一个类复杂某个功能领域中相应的职责,并于其他类协作完成任务。
- 适度内聚。有一个类复杂几个不同领域中的轻量级和单独的职责,这些领域在逻辑上于类的概念相关,但彼此之间并不相干。
根据经验,高内聚的类的方法数目较少、功能性有较强的关联,而且不需要做太多的工作。如果任务规模较大的化,它就于其他对象协作,共同完成这项任务。
高内聚的类优势明显,因为它易于维护、理解和服用,高度相关的功能性与少量的操作相结合,也可以简化维护和改进的工作。细粒度的,高度相关的功能性也可以提高夫哟管的潜力。
禁忌
在少数情况下,可以接受较低内聚。
一种情况时,将一组职责或代码放入一个类或构件中,以使某个人能方便低对其进行维护。
另一种情况时具有分布式服务器对象的低内聚构件。
优点
- 能够更加轻松、清楚低理解设计。
- 简化了维护和改进工作。
- 通常支持低耦合。
- 由于内聚的类可以用于某个特定的木笔,因此细粒度、相关性强的功能的重用性增强。