资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第七讲 对象设计,目标,学习使用面向对象设计的,5,个,GRASP,原则或模式,OOD,决定方法归属于哪个对象和对象之间如何交互,其意义重大,应谨慎从事。,掌握,OOD,可以通过在实例中学习和在设计中对模式的命名,建模的目的是为理解和沟通而不是构建文档,OOD,的解释:首先明确你的需求并创建领域模型,然后为适当的类添加方法,再定义对象之间的消息以实现需求,职责和职责驱动设计,UML,把职责定义为“类的契约或义务”。就对象的角色而言,职责与对象的义务和行为相关。职责分为以下两种类型:行为和认知,对象的行为职责包括:,自身执行一些行为,如创建对象或计算,初始化其他对象中的动作,控制和协调其他对象中的活动,对象的认知职责包括:,对私有封装数据的认知,对相关对象的认知,对其能够导出或计算的事物的认知,准则,对于软件领域对象来说,由于领域模型描述了领域对象的属性和关联,因此其通常产生与“认知”相关的职责。例如,如果领域模型的,Sale,类具有,time,属性,那么根据低表示差异的目标,软件的,Sale,类自然也应该知道其产生的时间,职责的粒度会影响到类和方法的转换。例,“,提供访问关系数据库”,“创建,Sale”,职责与方法并非同一事物,职责是一种抽象,而方法实现了职责,对象设计技巧与,UML,表示法技巧,绘制,UML,反映了对设计作出的决策,对象设计技术并不一定要了解如何绘制,UML,基本的对象设计需要了解的是:,职责分配原则,设计模式,对象设计,以迭代方法的设计示例,已经完成了哪些活动?,以前的活动和制品,事物之间具有什么样的关系?,以前的制品对,OO,设计的影响,需要完成多少设计建模工作,如何完成?,有哪些输出?,分析制品与对象设计之间有什么关系?,对象设计的输入是什么,场景,UML,包图,补充规格说明,词汇表,领域模型,对象设计中的活动,给定一个或多个输入,开发者有以下,3,个选择,:,1,:立即开发编码(理想的情况是用,测试优先开发,方式),2,:开发为对象设计进行一些,UML,建模,3,:利用其他建模技术,如,CRC cards.,对象设计中的活动,在,UML,案例中,真正要关注的并不是,UML,,而是可视化建模,即使用一种语言,这种语言比纯文本有更强的可视化功能。,方法是使用基于职责驱动设计,考虑怎样给协作中的对象分配职责,对象设计的输出,考虑,UML,交互图和类图,例如:,尤其对于对象设计而言,我们期望在开始编码之前针对设计中的难点创建,UML,交互图、类图和包图,UI,的草图和原型,数据库模型,报表的草图和原型,职责和职责驱动设计,思考软件对象设计以及大型构件的流行方式是,考虑其职责、角色和协作。这些被称为职责驱动设计的大型方法的一部分。,对象职责 其所作所为的抽象,职责,类元的契约或义务,就对象的角色而言,职责与对象的义务和行为相关,职责分为两种类型:,行为:,自身执行一些行为,如创建对象或计算,初始化其他对象中的动作,控制和协调其他对象中的活动,认知:,对私有封装数据的认知,对相关对象的认知,对其能够导出或计算的事物的认知,例如:,Sale,负责创建,SaleLineItems(,行为职责,),Sale,负责认知其总额(认知职责),职责方法,职责的粒度会影响到类和方法的转换,职责与方法并非同一事物,职责是一种抽象,而方法实现了职责,职责协作,RDD,也包括了协作的思想,职责借助于方法来实现,该方法既可以单独动作,也可以于其他方法和对象协作,职责协作,Sale,类可以定义一个或多个来获取其总额,比如命名为,getTotal,方法。为了完成该职责,,Sale,可能与其他对象协作,例如每个,SaleLineItem,对象发送,getSubtotal,消息以获取其小计金额,RDD,RDD,是思考,OO,软件设计的一般性隐喻,RDD,使我们把,OO,设计看作是有职责对象进行协作的共同体,GRASP,对一些基本的职责分配原则进行了命名和描述,因此掌握这些原则有助于支持,RDD,GRASP,GRASP,是通用职责分配软件模式(,General Responsibility Assignment Software Patterns,)的缩写,GRASP=,使用职责进行,OO,设计的学习工具,GRASP,原则或模式是一种学习工具,它能帮助你理解基本对象设计,并且以一种系统的、合理的、可以解释的方式来运用设计推理,对这种设计原则进行理解和使用的基础是分配职责的模式,目标:,以,GRASP,作为工具,帮助掌握,OOD,的基本知识并理解对象设计中的职责分配,职责、,UML,、,GRASP,在,UML,中,绘制交互图是考虑这些职责(实现为方法)的时机,GRASP,中的基本原则可以指导分配职责,当绘制,UML,交互图以及编写代码时,就可以运用,GARSP,原则了。,GRASP,的模式,GRASP,的,9,个模式如下所示:,创建者(,Creator,)控制器(,Controller,),纯虚构(,Pure Fabrication,)信息专家(,Information Expert,),高内聚(,High Cohesion,)间接性(,Indirection,),低耦合(,Low Coupling,)多态性(,Polymorphism,),防止变异(,Protected Variations,),GRASP,之一创建者,问题,:,谁有责任来创建类的实例?,创建者,名称:创建者(,Creator,),问题:谁创建了,A,?,解决方案(建议):如果以下条件之一为真时(越多越好),将创建类,A,实例的职责分配给类,B:,B”,包含”或组成聚集了,A,B,记录,A,B,直接使用,A,B,具有,A,的初始化数据,并且在创建,A,时会将这些数据传递给,A,如果有一个以上的选项适用,通常首先聚集或包含,A,的类,B,注意:,B,和,A,指的是软件对象,而不是领域模型对象,技巧:依靠,LRG,(低表示差异),来从领域模型中获得灵感,创建者,优点:支持低耦合,意味着它具有较低的维护依赖性和较高的复用性。,相关模式或原则:,低耦合,具体工厂和抽象工厂,整体,-,部分描述了定义聚合对象的模式,它支持对构件的封装,创建者,-,讨论,创建者模式指导我们分配那些与创建对象有关的职责。创建者模式的基本意图是寻找在任何情况下都与被创建对象具有连接的创建者。如此选择是为了保持低耦合。,有时,可以通过寻找具有初始化数据的类来确定创建者,这些数据将在创建过程中传递给被创建者,创建者,-,禁忌,对象的创建常常具有相当的复杂性,例如为了性能而使用回收的实例,基于某些外部特性值有条件地创建一个或一族类的实例,等等。在这些情况下,最好的方法是把创建职责委派给称为具体工厂(,Concrete Factory,)或抽象工厂(,Abstract Factory,)的辅助类,而不是使用创建者所建议的类,GRASP,之二信息专家,名称:信息专家(,Information Expert,),问题:给对象分配职责的基本原则是什么?,解决方案:把职责分配给具有完成该职责所需信息的那个类,信息专家,-,示例,Sale,time,Sales,LineItem,quantity,Product,Description,description,price,itemID,1,1.*,Contains,1,*,Described-by,信息专家-示例,问题:哪个类应当负责了解销售的总额?,按照信息专家(Information Expert)的建议,我们应当寻找具有确定总额所需信息的那个对象类。,问题:我们要查看领域模型或设计模型来分析具有所需信息的类?,答案:如果在设计模型中存在相关的类,首先查看设计模型;否则查看领域模型,并尝试利用(或扩充)它的表示,以激发相应设计类的创建,信息专家-示例,:Sale,t=getTotal,新方法,Sale,Time,getTotal(),信息专家-示例,:Sale,t=getTotal,新方法,Sale,time,getTotal(),Lineitemsi,SalesLineitem,1*:st=getSubtotal,SalesLineItem,quantity,getSubtotal(),这种表示法指明我们将遍历集合中的所有元素,信息专家-示例,:Sale,t=getTotal,Lineitemsi,SalesLineitem,1*:st=getSubtotal,Product,Description,1.1:p:=getPrice(),Sale,time,getTotal(),SalesLineItem,quantity,getSubtotal(),新方法,Product,Description,description,price,itemID,getPrice(),信息专家-示例,设计类,职责,Sale,知道销售的总额,SalesLineItem,知道商品的小计,ProductDescription,知道产品的价格,信息专家-示例,:Register,:Sale,p:Payment,makePayment(),1:create(),2:addPayment(P),信息专家-示例,:Register,:Payment,:Sale,makePayment(),1:makePayment(),1.1.create(),信息专家-示例,:Register,:ProcessSaleHandler,enterItem(id,quantity),enterItem(id,quantity),控制器的选择,信息专家-示例,:Register,:Payment,mackPayment(),create(),addPayment(p),:Sale,Register,创建,Payment,信息专家-示例,:Register,:Payment,mackPayment(),create(),:Sale,mackPayment(),GRASP,之三低耦合,问题:,怎样降低依赖性,减少变化带来的影响,提高重用性?,耦合是对某元素之间的连接、感知和依赖程度的度量。具有低(或弱)耦合的元素不会包括类、子系统、系统等,具有高(或强)耦合的类依赖于许多其他的类,这样的类或许不是我们所需要的。有些类会遇到以下问题:,由于相关类的变化而导致本体的被迫变化,难以单独地理解,由于使用高耦合类时需要它所依赖的类,因此很难重用,低耦合,名称:低耦合(,Low Coupling,),问题:如何减少因变化产生的影响?,解决方案:,分配职责以使(不必要的)耦合保持在较低的水平。利用这一原则来评估可选方案,GRASP,之四高内聚,问题:,怎样保持对象是有重点的、可理解的、可管理的,并且能够支持低耦合?,从对象设计的角度上说,内聚(或更为专业地说,是功能内聚)是对元素职责的相关性和集中度的度量。如果元素具有高度相关的职责,而且没有过多工作,那么该元素具有高内聚性。这些元素包括类、子系统等等。,高内聚,名称:高内聚(,High Cohesion,),问题:怎样使对象保持有内聚、可理解性和可管理性,同时具有支持低耦合的附加作用?,解决方案:职责分配应保持高内聚,依此来评估备选方案。,在实践中,内聚程度不能脱离其他职责及其他原则(如专家和低耦合)单独地考虑,GRASP,之五控制器,根据,MVS,原则,我们知道,UI,对象不应当包含应用逻辑或业务逻辑。因此,一旦,UI,对象获得了鼠标等事件,它们应该把该请求委派给领域层的领域对象,问题:,在,UI,层之上首先接收和协调(控制)系统操作的第一个对象是什么?,在,SSD,分析期间,要首先探讨系统操作。这些是我们系统的主要输入事件。例如,当使用,POS,终端的收银员按下“结束销售”按钮时,他就发起了表示“销售已经终止”的系统事件。类似地,当使用文字处理器的书写者按下“拼写检查”按钮时,他就发起了表示“执行拼写检查”的系统事件,控制器是,UI,层之上的第一个对象,它负责接收和处理系统操作消息,控制器,名称:控制器(,Controller,),问题:在,UI,层之上首先接受和协调(“控制”)系统操作的对象是什么?,解决方案:把职责分配给能代表以下选择之一的类:,代表整个“系统”、“根对象”、运行软件的设备或主要子系统(这些是外观控制器的所有变体)。,代表发生系统操作的用例场景(用例或会话控制器)。,正常情况下,控制器应当把需要完成地工作委派给其他的对象。控制器只是协调或控制这些活动,本身并不完成大量工作。,控制器,控制器,分析和设计,需求和面向对象分析重点关注学习做正确的事。后续的设计工作强调正确地做事,尽早引发变更,尽早编程、测试和演示有助于尽早引发不可避免的变更,谢谢大家!,
展开阅读全文