架构师培训6-类结构设计资料

上传人:我** 文档编号:114624343 上传时间:2019-11-12 格式:DOCX 页数:91 大小:1.10MB
返回 下载 相关 举报
架构师培训6-类结构设计资料_第1页
第1页 / 共91页
架构师培训6-类结构设计资料_第2页
第2页 / 共91页
架构师培训6-类结构设计资料_第3页
第3页 / 共91页
架构师培训6-类结构设计资料_第4页
第4页 / 共91页
架构师培训6-类结构设计资料_第5页
第5页 / 共91页
点击查看更多>>
资源描述

《架构师培训6-类结构设计资料》由会员分享,可在线阅读,更多相关《架构师培训6-类结构设计资料(91页珍藏版)》请在金锄头文库上搜索。

1、第六章 详细设计阶段的类结构设计详细设计阶段的一个十分重要的问题,就是进行类设计。类设计直接对应于实现设计,它的设计质量直接影响着软件的质量,所以这个阶段是十分重要的。这就给我们提出了一个问题,类是如何确定的,如何合理的规划类,这就要给我们提出一些原则,或者是一些模式。设计模式是有关中小尺度的对象和框架的设计。应用在实现架构模式定义的大尺度的连接解决方案中。也适合于任何局部的详细设计。设计模式也称之为微观架构模式。第一节 类结构设计中的通用职责分配软件模式 GRASP模式(General Responsibility Assignment Software Patterns 通用职责分配软件模

2、式)能够帮助我们理解基本的对象设计技术,并且用一种系统的、可推理的、可说明的方式来应用设计理论。一、根据职责设计对象 职责:职责与一个对象的义务相关联,职责主要分为两种类型:1)了解型(knowing)了解私有的封装数据;了解相关联的相关对象;了解能够派生或者计算的事物。2)行为型(doing)自身执行一些行为,如建造一个对象或者进行一个计算;在其它对象中进行初始化操作;在其它对象中控制或者协调各项活动。职责是对象设计过程中,被分配给对象的类的。我们常常能从领域模型推理出了解型相关的职责,这是因为领域模型实际上展示了对象的属性和相互关联。二、职责和交互图 在UML中,职责分配到何处(通过操作来

3、实现)这样的问题,贯穿了交互图生成的整个过程。例如:所以,当交互图创建的时候,实际上已经为对象分配了职责,这体现到交互图就是发送消息到不同的对象。三、在职责分配中的通用原则 总结一下:l 巧妙的职责分配在对象设计中非常重要。l 决定职责如何分配的行为常常在创建交互图的之后发生,当然也会贯穿于编程过程。l 模式是已经命名的问题/解决方案组合,它把与职责分配有关的好的建议和原则汇编成文。四、信息专家模式 解决方案:将职责分配给拥有履行一个职责所必需信息的类,也就是信息专家。问题:在开始分配职责的时候,首先要清晰的陈述职责。假定某个类需要知道一次销售的总额。根据专家模式,我们应该寻找一个对象类,它具

4、有计算总额所需要的信息。关键:使用概念模型(现实世界领域的概念类)还是设计模型(软件类)来分析所具有所需信息的类呢?答:1 如果设计模型中存在相关的类,先在设计模型中查看。2 如果设计模相中不存在相关的类,则查看概念模型,试着应用或者扩展概念模型,得出相应的概念类。我们下面来讨论一下这个例子。假定有如下概念模型。到底谁是信息专家呢?如果我们需要确定销售总额。可以看出来,一个Sale类的实例,将包括“销售线项目”和“产品规格说明”的全部信息。也就是说,Sale类是一个关于销售总额的合适的信息专家。而SalesLineItem可以确定子销售额,这就是确定子销售额的信息专家。进一步,ProductS

5、pecification能确定价格等,它就是“产品规格说明”的信息专家。上面已经提到,在创建交互图语境的时候,常常出现职责分配的问题。设想我们正在绘设计模型图,并且在为对象分配职责,从软件的角度,我们关注一下:为了得到总额信息,需要向Sale发出请求总额请求,于是Sale得到了getTotal方法。而销售需要取得数量信息,就要向“销售线项目”发出请求,这就在SalesLineItem得到了getSubtotal方法。而销售线项目需要向“产品规格说明”取得价格信息,这就在ProductSpecification类得到了getPrice方法。这样的思考,我们就在概念模型的基础上,得到了设计模型。注

6、意:职责的实现需要信息,而信息往往分布在不同的对象中,这就意味着需要许多“部分”的信息专家来协作完成一个任务。信息专家模式于现实世界具有相似性,它往往导致这样的设计:软件对象完成它所代表的现实世界对象的机械操作。但是,某些情况下专家模式所描述的解决方案并不合适,这主要会造成耦合性和内聚性的一些问题。后面我们会加以讨论。五、创建者模式 解决方案:如果符合下面一个或者多个条件,则可以把创建类A的职责分配给类B。1,类B聚和类A的对象。2,类B包含类A的对象。3,类B记录类A的对象的实例。4,类B密切使用类A的对象。5,类B初始化数据并在创建类A的实例的时候传递给类A(因此,类B是创建类A实例的一个

7、专家)。如果符合多个条件,类B聚合或者包含类A 的条件优先。问题:谁应该负责产生类的实例?创建对象是面向对象系统最普遍的活动之一,因此,拥有一个分配创建对象职责的通用原则是非常有用的。如果职责分配合理,设计就能降低耦合度,提高设计的清晰度、封装性和重用性。讨论:创建者模式指导怎样分配和创建对象(一个非常重要的任务)相关的职责。通过下面的交互图,我们立刻就能发现Sale具备Payment创建者的职责。创建者模式的一个基本目的,就是找到一个在任何情况下都与被创建对象相关联的创建者,选择这样的类作为创建者能支持低耦合。限制:创建过程经常非常复杂,在这种情况下,最好的办法是把创建委托给一个工厂,而不是

8、使用创建者模式所建议的类。六、低耦合模式 解决方案:分配一个职责,是的保持低耦合度。问题:怎样支持低的依赖性,减少变更带来的影响,提高重用性?耦合(coupling)是测量一个元素连接、了解或者依赖其它元素强弱的尺度。具有低耦合的的元素不过多的依赖其它的元素,“过多”这个词和元素所处的语境有关,需要进行考查。元素包括类、子系统、系统等。具有高耦合性地类过多的依赖其它的类,设计这种高耦合的类是不受欢迎的。因为它可能出现以下问题:l 相关类的变化强制局部变化。l 当元素分离出来的时候很难理解l 因为使用高耦合类的时候需要它所依赖的类,所以很难重用。示例:我们来看一下订单处理子系统中的一个例子,有如

9、下三个类。Payment(付款)Register(登记)Sale(销售)要求:创建一个Payment类的实例,并且与Sale相关联。哪个类更适合完成这项工作呢?创建者模式认为,Register记录了现实世界中的一次Payment,因此建议用Register作为创建者。第一方案:由Register构造一个Payment对象。再由Register把构造的Payment实例通过addPayment消息发送给Sale对象。第二方案:由Register向Sale提供付款信息(通过makePayment消息),再由Sale创建Payment对象。两种方案到底那种支持低的耦合度呢?第一方案,Register

10、构造一个Payment对象,增加了Register与Payment对象的耦合度。第二方案,Payment对象是由Sale创建的,因此并没有增加Register与Payment对象的耦合度。单纯从耦合度来考虑,第二种方案更优。在实际工作中,耦合度往往和其它模式是矛盾的。但耦合性是提高设计质量必须考虑的一个因素。讨论:在确定设计方案的过程中,低耦合是一个应该时刻铭记于心的原则。它是一个应该时常考虑的设计目标,在设计者评估设计方案的时候,低耦合也是一个评估原则。低耦合使类的设计更独立,减少类的变更带来的不良影响,但是,我们会时时发现低耦合的要求,是和其它面向对象的设计要求是矛盾的,这就不能把它看成唯

11、一的原则,而是众多原则中的一个重要的原则。比如继承性必然导致高的耦合性,但不用继承性,这就失去了面向对象设计最重要的特点。没有绝对的尺度来衡量耦合度,关键是开发者能够估计出来,当前的耦合度会不会导致问题。事实上越是表面上简单而且一般化的类,往往具有强的可重用性和低的耦合度。低耦合度的需要,导致了一个著名的设计原则,那就是优先使用组合而不是继承。但这样又会导致许多臃肿、复杂而且设计低劣的类的产生。所以,一个优秀的设计师,关键是用一种深入理解和权衡利弊的态度来面对设计。设计师的灵魂不是记住了多少原则,而是能灵活合理的使用这些原则,这就需要在大量的设计实践中总结经验,特别是在失败中总结教训,来形成自

12、己的设计理念。设计师水平的差距,正在于此。七、高内聚模式解决方案:分配一个职责,使得保持高的内聚。问题:怎么样才能使得复杂性可以管理?从对象设计的角度,内聚是一个元素的职责被关联和关注的强弱尺度。如果一个元素具有很多紧密相关的职责,而且只完成有限的功能,那这个元素就是高度内聚的。这些元素包括类、子系统等。一个具有低内聚的类会执行许多互不相关的事物,或者完成太多的功能,这样的类是不可取的,因为它们会导致以下问题:1,难于理解。2,难于重用。3,难于维护。4,系统脆弱,常常受到变化带来的困扰。低内聚类常常代表抽象化的“大粒度对象”,或者承担着本来可以委托给其它对象的职责。示例:我们还是来看一下刚刚

13、讨论过的订单处理子系统的例子,有如下三个类。Payment(付款)Register(登记)Sale(销售)要求:创建一个Payment类的实例,并且与Sale相关联。哪个类更适合完成这项工作呢?创建者模式认为,Register记录了现实世界中的一次Payment,因此建议用Register作为创建者。第一方案:由Register构造一个Payment对象。再由Register把构造的Payment实例通过addPayment消息发送给Sale对象。第二方案:由Register向Sale提供付款信息(通过makePayment消息),再由Sale创建Payment对象。在第一个方案中,由于Reg

14、ister要执行多个任务,在任务很多的时候,就会显得十分臃肿,这种要执行多个任务的类,内聚是比较低的。在第二种方案里面,由于创建Payment对象的任务,委托给了Sale,每个类的任务都比较简单而且单一,这就实现了高的内聚性。从开发技巧的角度,至少有一个开发者要去考虑内聚所产生的影响。一般来说,高的内聚往往导致低的耦合度。讨论:和低耦合性模式一样,高内聚模式在制定设计方案的过程中,一个应该时刻铭记于心的原则。同样,它往往会和其它的设计原则相抵触,因此必须综合考虑。Grady Booch是建模的大师级人物,它在描述高内聚的定义的时候是这样说的:“一个组件(比如类)的所有元素,共同协作提供一些良好

15、受限的行为。”根据经验,一个具有高内聚的类,具有数目相对较少的方法,和紧密相关的功能。它并不完成太多的工作,当需要实现的任务过大的时候,可以和其它的对象协作来分担过大的工作量。一个类具有高内聚是非常有利的,因为它对于理解、维护和重用都相对比较容易。限制:少数情况下,接受低内聚是合理的。比如,把SQL专家编写的语句综合在一个类里面,这就可以使程序设计专家不必要特别关注SQL语句该怎么写。又比如,远程对象处理,利用很多细粒度的接口与客户联系,造成网络流量大幅度增加而降低性能,就不如把能力封装起来,做一个粗粒度的接口给客户,大部分工作在远程对象内部完成,减少远程调用的次数。第二节 设计模式与软件架构一、设计模式在模块设计阶段,

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号