第10章面向对象设计第10章面向对象设计10.1面向对象的设计准则10.2问题域子系统设计10.3人机交互子系统设计10.4任务管理子系统设计10.5数据管理子系统设计10.6服务与关联的设计10.7面向对象设计的优化第10章面向对象设计10.1面向对象的设计准则10.1.1设计准则1.模块化模块化是软件设计的重要准则。在面向对象开发方法中,将对象定义为模块。对象把数据结构和作用在数据上的操作封装起来构成模块。对象是组成系统的基本模块。第10章面向对象设计2.抽象类是一种抽象数据类型,在该数据类型之上,可以创建对象(类的成员)。类包含相似对象的共同属性和服务,它对外定义了公共接口,构成了类的规格说明(即协议),供外界合法访问。通过这种接口访问类实例中的数据。通常把这类抽象称为规格说明抽象。3.信息隐藏在面向对象方法中,对象是属性和服务的封装体,这就实现了信息隐藏。类结构分离了接口与实现,类的属性的表示方法和操作的实现算法,对于类的用户来说,都应该是隐藏的,用户只能通过公共接口访问类中的属性。第10章面向对象设计4.弱耦合所谓耦合,是指一个软件结构内不同模块之间互连的依赖关系。依赖关系越多耦合度越强,依赖关系越少耦合度越弱。在面向对象方法中,对象是最基本的模块,不同对象之间相互关联的依赖关系表示了耦合度。衡量设计优良的一个重要标准就是弱耦合,弱耦合的设计中某个对象的改变不会或很少影响到其他对象。这样给理解、测试或修改带来很大的方便。反之,强耦合会给理解、测试或修改带来很大的难度,并且还降低了该类的可重用性和可移植性。不同对象之间耦合是不可避免的。两个对象必须相互联系相互依赖时,应该通过类的协议(即公共接口)实现两个对象相互依赖(耦合),而不是通过类的具体实现细节来描述。第10章面向对象设计5.强内聚所谓内聚,是一个模块内各个元素彼此结合的紧密程度。结合得越紧密内聚越强,结合得越不紧密内聚越弱。强内聚也是衡量设计优良的一个重要标准。在面向对象设计中,内聚可分为下述三类:(1)服务内聚。一个服务应该是单一的,即只完成一个任务。(2)类内聚。类内聚要求类的属性和服务应该是高内聚的,而且它们应该是系统任务所必需的。一个类应该只有一个功能,如果某个类有多个功能,通常应该把它分解成多个专用的类。第10章面向对象设计(3)一般-特殊内聚。一般-特殊内聚表示:一般-特殊结构符合领域知识的表示形式,也就是说,特殊类应该尽量地继承一般类的属性和服务。这样的一般-特殊结构是高内聚的。例如,虽然表面看来飞机与汽车有相似的地方(都用发动机驱动,都有轮子,……),但是,如果把飞机和汽车都作为“机动车”类的子类,则不符合领域知识的表示形式,这样的一般-特殊结构是低内聚的。高内聚的一般-特殊结构应该是,设置一个抽象类“交通工具”,把飞机和机动车作为交通工具类的子类,而汽车又是机动车类的子类。第10章面向对象设计6.可重用在面向对象设计中,一个类的设计应该具有通用性,为开发相似的系统提供软件重用可能。软件重用可以提高软件开发生产率,确保目标系统质量。可重用是面向对象开发方法的一个重要特性,也就是说,用面向对象的概念和方法比较容易实现重用。因此,在软件开发过程中,为了实现重用,既要尽量重用已有的类,又要创建可重用的新类。第10章面向对象设计10.1.2设计策略在使用面向对象方法学开发软件的实践中,得出了下面一些基于经验的启发规则,这些规则往往能帮助软件开发人员设计出好的方案来,以保证软件的质量。1.设计结果应该清晰易懂良好的设计结果应该是清晰易懂的,它能提高软件的可维护性和可重用性。如果一个设计结构不清楚,并且难以理解,是不会被人们接受的。设计时采用以下几个策略能使结果清晰易懂。(1)命名一致。命名应该与专业领域中的名字一致,并且要是符合人们习惯的名字。不同类中相似服务的名字应该相同。第10章面向对象设计(2)重用协议(公共接口)。在设计中应该使用已经建立了类的协议,避免重复劳动或重复定义带来的差异(不统一)。这些协议可能是其他设计人员已经建立了类的协议,或是在类库中已有的协议。(3)减少消息连接。尽量采用已有标准的消息连接,去掉不必要的消息连接。采用统一模式建立自己需要的消息连接,以便理解和使用,增强可理解性和可使用性。(4)避免模糊的定义。应该定义具有明确、有限用途的类,避免那些模糊的、不准确的类定义。第10章面向对象设计2.一般-特殊结构的深度应适当从基类派生子类,再从子类派生下一层子类,这样的一般-特殊结构的类层次数应该适当,不必过于细化,层次的深度应该是有限的。一般来说,在一个中等规模(大约包含100个类)的系统中,类层次数应保持为7±2。第10章面向对象设计3.设计简单的类类设计应该尽量小而简单,便于开发和管理。定义很大的类,它所包含的属性和服务相对就多,会给开发和使用带来困难。实践表明,简单类一个类的定义在50行左右(或两屏)。简单类可按照下列的策略定义。(1)避免包含太多的属性。一个类包含的属性多少将决定类的复杂程度。一个类包含太多的属性表明该类过于复杂了,因此,就可能有过多的作用在这些属性上的服务。(2)避免提供太多服务。一个类包含的服务多少也是决定类的复杂程度的一个重要因素。太复杂的类所提供的服务肯定太多。一般来说,一个类提供的公共服务不要超过七个。第10章面向对象设计(3)明确精练的定义。如果一个类的任务简单了,则它的定义就明确精练了,通常任务简单的类可用几个简单语句描述。(4)简化对象间的通信。每个对象应该独立完成任务。也就是说,对象在完成任务时,尽量不要依赖于其他对象的配合(帮助),对象之间过多的依赖会破坏类的简明性和清晰性。虽然,遵循上述设计策略能设计出明确精练的较小的类,但在开发大型软件系统中,必定会有大量较小的类设计出来,这将会导致类间的通信变复杂。采用划分“主题”的方法,可以解决这个问题。第10章面向对象设计4.设计简单的协议消息中的参数越多表示对象之间传递的消息越复杂,同样表明对象之间的依赖关系越复杂,即对象间的耦合度越高。一般来说,简单消息中的参数不要超过三个。过多的参数会导致对象的修改较复杂,因为对一个对象的修改往往导致其他对象的修改。第10章面向对象设计5.设计简单的服务类中的服务应该设计得既简单又小,用3~5行源程序代码比较适合。服务的源程序中不要包含过多的语句行,或者复杂的语句控制结构,如分支嵌套、循环嵌套和函数调用等。如果一个服务非常复杂,则应该检查该服务的控制结构,并进行分解和简化,尽量避免设计复杂的服务。第10章面向对象设计6.减少设计变动随着设计方案逐渐成熟,改动也应该越来越小,这样才能设计出优良的结果。优良的设计能保证软件质量,并能提高软件的可重用性。因此,在设计中尽可能少改动,或者尽可能缩小修改的范围。第10章面向对象设计10.1.3系统分解与组织面向对象设计同过程设计一样,自顶向下进行功能分解。在设计比较复杂的应用系统时,将系统分解成若干个比较小的部分,再分别设计每个部分。这样既简化了应用系统,又降低了设计的难度,并有利于实现和维护。第10章面向对象设计系统是根据功能来分解的,我们将系统分解的各个部分(即系统的主要组成部分)称为子系统。例如,编译系统可划分成词法分析、语法分析、中间代码生成、优化、目标代码生成和出错处理等子系统。子系统不是单一的对象或功能,而是面向对象分析模型的五个层次的集合。子系统的划分不能太多,要与系统规模相匹配,最底层的子系统成为模块。子系统间交互的形式和交互的信息由接口确定,因此,接口应该简单、明确,以便设计出相对独立的子系统,减少子系统的依赖性。第10章面向对象设计1.面向对象设计的五个层次、四个部分面向对象设计是在面向对象分析模型的基础上建立对象模型的过程。两个阶段同样是建立对象模型,只是面向对象分析建立了问题域的对象模型,而面向对象设计建立的是求解域的对象模型。因此,面向对象设计模型同样由主题、类-&-对象、结构、属性和服务等五个层次组成,并且又扩充了问题域(PDC)、人机交互(HIC)、任务管理(TMC)和数据管理(DMC)四个部分。第10章面向对象设计这五个层次就像五个透明的图层,而整个模型像是由五个图层(水平切片)合并而成的,五个层次一层比一层描述得更具体、更明确;四大组成部分又可想象成为整个模型的四个垂直切片。不同的应用系统中,这四个子系统的侧重程度和规模都不同,应该根据系统规模的大小确定子系统的数目。在复杂的系统中,子系统可能要继续分解;对于小系统来说,可能要合并小的子系统。典型的面向对象设计模型如图10.1所示。第10章面向对象设计图10.1典型的面向对象设计模型人机界面HICPDCTMCDMC问题论域任务管理数据管理主题层类-&-对象层结构层属性层服务层第10章面向对象设计2.子系统间的交互方式在应用系统中,子系统之间的关系可分为客户/服务器关系和同等伙伴关系两种。这两种关系对应两种交互的方式,即客户/服务器交互方式和同等伙伴交互方式。(1)客户/服务器交互方式。客户/服务器交互方式也称单向交互方式。在客户/服务器关系中,作为“客户”的子系统调用作为“服务器”的子系统,执行某些服务后并返回结果。在该交互方式中,任何交互行为都是由客户驱动的,因此,作为客户的子系统必须了解作为服务器的子系统的接口,而服务器不必了解客户的接口。第10章面向对象设计(2)同等伙伴交互方式。同等伙伴交互方式也称双向交互方式。在该交互方式中,每个子系统都可能调用其他子系统,因此,每个子系统都必须了解其他子系统的接口,子系统间必须相互了解接口。与客户/服务器关系比较,同等伙伴交互关系中子系统之间的交互更复杂,而且这种交互方式还可能构成通信环路,会给设计带来难度,并容易出现设计错误。通常,系统使用客户/服务器关系,因为单向交互更容易理解,也更容易设计和修改,而双向交互相对困难些。第10章面向对象设计3.系统组织将子系统组织成完整的系统有两种方式,即水平层次组织和垂直块组织。1)层次组织层次组织是将子系统按层组织成为一个层次软件系统,每层是一个子系统。上层建立在下层的基础上,下层为上层提供必要的服务。各层内所包含的对象是相互独立的,而不同层次上的对象,相互间有关联。低层子系统提供服务,相当于服务器,上层子系统使用下层提供的服务,相当于客户。这样构成上、下层之间的客户/服务器关系。这种组织方式使软件系统形成层次结构。第10章面向对象设计层次结构又可分为封闭式和开放式两种。在封闭式结构中,每层子系统只根据相邻下层建立,且仅使用相邻下层提供的服务。这种方式降低了各层次之间的相互依赖性,更容易理解和修改,因为一个层次的接口只影响与其相邻的上一层。在开放式结构中,某层子系统可以使用其下面的任何一层子系统所提供的服务。该方式减少了各层上重新定义的服务的需求,使得整个系统更高效、更紧凑。但是,该方式没有遵守信息隐藏的原则,对任何一个子系统的变更都会影响到更高层次的那些子系统。设计软件系统时应该权衡设计准则的各因素而决定组织系统结构的方式。第10章面向对象设计通常,在需求陈述中只描述了系统的顶层和底层的内容,顶层就是用户看到的目标系统,底层则是可以使用的资源(如硬件、操作系统、数据库等)。这两层间差异很大,为了减少不同层次之间的概念差异,设计者必须引入一些中间层次来弥补。第10章面向对象设计2)块组织块组织将系统垂直地分解成若干个相对独立的、弱耦合的子系统,一个子系统相当于一块,每块提供一种类型的服务。在一个系统中,可利用层次和块的混合组织方式。各种可能的组合结构,可以成功地把多个子系统组成一个完整的、混合结构的软件系统。在混合结构组织中,同一层次可以由若干块组成,而同一块也可以分为若干层。大多数复杂系统组织采用层次与块的混合结构。例如,图10.2表示一个典型应用系统的组织结构。第10章面向对象设计图10.2典型应用系统的组织结构计算机硬件操作系统人机交互控制像素图形屏幕图形窗口图形仿真软件包应用包第10章面向对象设计4.设计系统的拓扑结构构成完整系统的拓扑结构有:管道型、树型、星型等。为了减