软件工程 第八章 面向对象的设计方法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第八章面向对象的设计方法
本章采用基于UML的面向对象设计方法的将分析模型转换为设计模型。

如第五章所述,面向对象的分析模型主要由顶层架构图、用例与用例图、领域概念模型构成;设计模型则包含以包图表示的软件体系结构图、以交互图表示的用例实现图、完整精确的类图、针对复杂对象的状态图和用以描述流程化处理过程的活动图等。

为完成这一转换过程,设计人员必须处理以下任务:
(1)针对分析模型中的用例,设计实现方案。

实现方案用UML交互图表示。

(2)设计技术支撑设施。

在大型软件项目中,往往需要一些技术支撑设施来帮助业务需求层面的类或子系统完成其功能。

这些设施本身并非业务需求的一部分,但却为多种业务需求的实现提供公共服务。

例如,数据的持久存储服务、安全控制服务和远程访问服务等。

在面向对象设计中,需要研究这些技术支撑设施的实现方式以及它们与业务需求层面的类及子系统之间的关系。

(3)设计用户界面。

(4)针对分析模型中的领域概念模型以及第(2)、(3)两个步骤引进的新类,完整、精确地确定每个类的属性和操作,并完整地标示类之间的关系。

此外,为了实现软件重用和强内聚、松耦合等软件设计原则,还可以对前面形成的类图进行各种微调,最终形成足以构成面向对象程序
设计的基础和依据的详尽类图。

面向对象的软件设计过程如图8-1-1所示。

图8-1-1 面向对象的软件设计过程
第一节设计用例实现方案
UML 的交互图(顺序图、协作图)适于用例实现方案的表示。

因此,本节首先介绍交互图的语言机制,然后探讨用例实现方案的设计方法。

该设计方法包含如下3个步骤:
(1)提取边界类、实体类和控制类;
(2)构造交互图;
(3)根据交互图精华类图。

一、顺序图
顺序图用来描述对象之间动态的交互关系,着重表现对象间消息传递的时间顺序。

在顺序图中,参与交互的对象位于顶端的水平轴上,垂直轴表示时间,时间推移的方向是自上而下的。

顺序图中的对象一般以“对象
名:类名”的方式标识,但也可以仅采用缩写形式“对象名”或者“:类名”。

对象的下方用垂直虚线表示对象的生命线,即对象在某段时间内存在。

对象生命的终结用生命线下方的叉号“′”表示。

附着在对象生命线上的矩形框表示对象在此段时间内活跃。

对象间的通信表现为对象的生命线之间的消息传递。

在消息边上需附加消息名和消息参数,有时也以顺序号强调消息的时序。

消息的源对象和目标对象可以相同,这种消息称为自调用(self-call)。

可以在消息名前面的方括号中书写条件表达式,表明仅当条件成立时,该消息才发送。

还可以在方括号的前面或者直接在消息名的前面加上迭代标记“*”,以表示一条消息对同一类的多个对象的多次发送。

顺序图的左边可带有描述信息,以阐明消息发送的时刻、动作执行情况、两条消息之间的时间间隔以及约束信息等。

还可以在消息边上附加文字注解信息,以增强顺序图的可理解性。

典型的顺序图如图8-1-2所示。

UML的消息有如下4种类型:
(1)简单消息(simple message)。

以一种简单、抽象的函数表示对象之间的信息传递,不考虑通信过程的内部细节。

简单消息在UML顺序图中用普通的有向箭头表示。

(2)同步消息(synchronus message)。

消息源发出消息后,必须等待消息处理过程完毕并返回处理结果,才可继续执行后续操作。

前面所述的自调用消息应该是同步的。

同步消息的表示图元与简单消息相同,这表明UML在缺省状态下认为简单消息即为同步消息。

(3)异步消息(synchonous message)。

消息源发出消息后,不必等待消息处理过程的返回,即可继续执行自己的后续操作。

异步消息主要用于描述实时系统中的并发行为。

异步消息在UML顺序图中用一种特别的单向箭头表示,见图8-1-2中的“msg1”。

图8-1-2 典型的顺序图
(4)返回消息(return message)。

表示前面发送的消息的处理过程完成后的返回结果。

返回消息应该是同步。

在许多情况下,可以隐藏返回消息,但也可显式地标出返回消息以示强调。

返回消息用虚线有向箭头表示,见图8-1-2中的“msg6”。

一个对象可以通过发送标准消息“new”来创建另一个对象。

当一个对象被删除或自我删除时,该对象生命线上的相应时间点应该用叉号(对象生命线终结符)标识。

二、协作图
协作图用于描述相互合作的对象间的交互关系和链接关系。

虽然顺序图和协作图都用来描述对象间的交互关系,但它们的侧重点不同。

顺序图强调消息交互的时间序列,而协作图则强调交互对象间的静态链接关系。

从外观看,协作图并不采用单独的维度来表示时间的推移,因此,协作图中的对象可以在二维平面中自由占位。

对象之间的链接用于表示消息传递的通道,消息标示于链接之上,消息的箭头指明消息的传递方向。

协作图中,消息的描述内容包含名称、参数、返回值以及序列号是可选的。

虽然协作图不突出强调消息传递的时间序,但借助于序列号同样可以表达时间序:序列号较大的消息发生于较晚的时刻。

消息序列号可以采用线性编号,但采用适当的多级编号会使消息之间的结构关系更清晰,例如,在图8-1-3中,“1.1msg2 ”是“对象1”为了处理“1.mag1 ”而发送的第二条消息,“1.1.1msg3”表明mag3“是对象2”为了处理“1.1 msg2”而发送的第一条消息,依此类推。

如果一个对象在消息的交互过程中创建,则可在对象名称之后标以{new}。

类似地,如果一具对象在交互期间被删除,则可在对象名称之后标以{destroy}。

典型的协作图如图8-1-3所示,该协作图与图8-1-2等价。

图8-1-3 典型的协作图
三、提取边界类、实体类和控制类
边界类用于描述目标软件系统与外部环境之间的交互,并负责实现如下功能:
(1)界面控制。

包括输入数据的格式及内容转换、输出结果的呈现以及软件运行过程中界面的变化与切换等。

(2)外部接口。

实现目标软件系统与外部系统或外部设备之间的信息交流和互操作。

主要关注跨越目标软件系统边界的通信协议。

(3)环境隔离。

将目标软件系统与操作系统、数据库管理系统、应用服务器中间等环境软件进行交互的功能与特性封装于边界类之中,使目标软件系统的其余部分尽可能的独立于环境软件。

在UML 类图中,边界类往往附加UML 构造型<<boundary>>作为特别标识。

例如,“家庭保安系统”中的边界类有“输入键盘接口类”、“传感器接口类”、“警报器接口类”、“报警电话接口类”和“显示面板接口类”。

实体在表示目标软件系统中具有持久意义的信息项及其操作。

实体类的操作具有“内向收敛”特征,它们仅向目标软件系统的其余部分提供读/写信息项内容的必要的操作接口,并不涉及业务逻辑处理。

实体类的UML构造型为<<entity>>。

例如,“家庭保安系统”中的“异常事件”即为实体类。

控制类作为完成用例任务的责任承担者,协调、控制其他类共同完成用例规定的功能或行为。

对于比较复杂的用例,控制类通常并不处理具体的任务细节,但是它应知道如何分解任务,如何将子任务分派给适当的辅助类,以及如何在辅助类之间进行消息传递和协调。

控制类的UML构造型为<<control>>。

例如,“家庭保安系统”中的“用户命令处理器”和“监测器”均为
控制类。

在讨论了边界类、实体类和控制类和基本概念之后,下面介绍如何从分析模型中的用例描述和领域概念模型出发获取这些类。

通常情况下,执行者与用例之间的一种通信连接对应一个边界类。

但是,如果两个以上的用例与同一执行者交互,并且这些交互具有共同的行为、完成相同或类似的任务,就可以考虑用同一边界类实现用例与执行者之间的交互。

这就意味着边界类的作用范围可以超越单个用例。

实体类主要来源于领域概念模型。

有时也需要认真研读用例描述,从中发掘具有持久意义的信息项。

如果执行者的属性需要持久保存,也可以建立相应于执行者的实体类。

假设一个实体类A仅仅被系统中的另一个类B 引用,并且系统无需关心类A有行为特征,那么为了简化设计模型,应将类A中的信息项直接作为类B的属性。

反之,如果类A被系统中的多个类引用,或者类A具有不容忽略的行为特征,那么应将类A作为独立的实体类。

一般而言,一个用例通常对应一个控制类。

如果不同用例的任务较多类似之处,也可以考虑在多个用例的实现方案中共享一个控制类。

不过,此种情况应审慎对待,因为对于不同的且例,其事件流的逻辑结构鲜有雷同,它们所需要的控制、协调行为往往会有差异。

此外,对于那些事件流
非常简单的用例,可以不设独立的控制类,直接在边界类中设置控制、协调功能,边界类在实体类的帮助下完成用例要求的功能及行为。

四、构造交互图
在标识边界类、实体类和控制类之后,接下来的任务是将分析模型中的用例描述转化成UML交互图,以交互图作为用例的精确实现方案。

如前所述,用例描述中已包含事件流说明。

事件流中的事件应直接对应于交互图中的消息,而事件间的先后关系体现为交互图中的时序,对消息的响应则构成消息接收者的职责。

这种职责在后续的设计活动中将被确立为类的方法。

对于比较复杂的用例而言,仅仅依靠控制类、边界类和实体并不能很好地解决问题,因为我们不能使单个控制类过于宏大和复杂,让它既承担控制、协调的任务,又承担复杂的计算任务。

因此,在设计复杂用例的实施方案时,应考虑为控制类设置一些独立的辅助类,让控制类将一些任务委托给辅助类完成。

例如,在图5-3-4所示的“家庭保安系统”类图中,“系统配置管理器”和“日志管理器”就是这种意义上的辅助类。

在UM顺序图中,用例的主动执行者应位于最左侧,紧邻其右的类的作为用户界面的边界类,再往右是控制类。

控制类的右侧应旋转辅助类和实体类,它们的右侧是人秋外部接口和环境隔离层的边界类,最右侧是痊
于目标软件系统边界之外的被动执行者。

如此布局之后,在顺序图中不应该出现穿越控制类生命线的消息,即主动执行者向边界类发出命令,边界类将命令进行适当转换后传送至控制类,控制类通过消息请求辅助类、实体类的帮助,协调、控制它们共同完成来自主动执行者的命令。

在此过程中,控制类或辅助害可以向右侧的边界类发送消息,将信息或外部处理请求由边界类传向外部系统(被动执行者)。

按照上述而已规则绘制的典型的顺序图如图8-1-4所示。

图8-1-4 典型布局规则下的顺序图
在用例描述中,许多用例除主事件流外,往往还包含备选事件流,以说明在某些特殊或异常情况下的事件和响应动作序列。

为易于理解,在设计模型中应该用分离的UML交互图分别表示事件流和每个备选事件流。

由于顺序图能够非常直观地表达事件(消息)的时序,所以它比协作图更多地用于描述用例的实现方案。

但是,当需要强调类之间的联系或连接时,就需要绘制协作图。

协作图的而已规则是:控制类位于中心,主动执行者和作为用户界面的边界类位于左上方,作为外部接口和环境隔离层的边界类位于右上方,辅助类和实体类分别位于控制类的左下方和右下方。

按照此而已规则绘制的典型的协作图如图8-1-5所示。

图8-1-5 典型布局规则下的协作图
在“家庭保安系统”中用例“传感器监测”和“命令处理”的实现方案分别见图8-1-6和图8-1-7。

为简洁起见,图8-1-6和图8-1-7未表示这两个用例中的日志功能,图8-1-7也未考虑配置命令的处理,有兴趣的读者可自行添加。

图8-1-6 “传感器监测”用例的顺序图
图8-1-7 “命令处理”用例的顺序图五、精华类图
在UML交互图中,对每个类的对象都规定了它必须响应的消息以及类的对象之间的消息传递通道。

前者对应于类的操作,后者则对应于类之间的连接关系。

因此,可以利用交互图精华分析模型中的类图,将交互图中出现的新类添加到原有类图中,并且对相关的类进行精华,定义其属性和操作。

原则上,每个类都应该有一个操作来响应交互图中指向其对象的那条消息。

但是,这并不意味着消息与操作一定会一一对应,因为类的一个操作可能具有响应多条消息的能力。

同理,两个类之间的一条连接关系也可以为多条消息提供传递通道。

为了简化设计模型,也为了提高重用程度,设计人员应该尽量使用已有的操作来响应新消息,并尽量使用已存在的连接路径作为消息传递的通道。

如果两个类之间存在明确、自然的聚合或组合关系,则可以在类图中直接用相应的UML图元符号表示类间的聚合或组成关系,这两个关系均可提供消息传递通道。

接下来讨论如何根据交互图确立类的属性。

类的操作完成消息响应责任的能力来源于两方面的知识,一是类本身具有的信息,即类的属性;二是类能够找到的其他类,通过其他类协助其完成消息响应,在综合考虑这两个因素之后,类的操作应该明确哪些子任务可通过消息传递路径委托给其他类完成,哪些子任务必须由自身完成。

根据后一种子任务的需要结合领域和业务知识即可推导出类应具有的属性。

在图5-3-4的基础上,得出“家庭保安系统”的类图如图8-1-8所示。

为简洁起见,图8-1-8仅标出控制类“监测器”和“用户命令处理器”的方法以及实体类“异常事件”的属性,有兴趣的读者可自行添加其余的属性和方法。

图8-1-8 “家庭保安系统”的精化类图
第二节设计技术支撑方案
在许多软件项目中,应用功能往往都需要一组技术支撑机制为其服务。

例如,分布式应用软件(包括电子商务应用、企业ERP系统等)而言,需要数据持久存储服务、安全控制服务、分布式事务管理服务、并发与同步控制服务和可靠消息服务等。

这些技术支撑设施并非业务需求的直接组成部分,但形态各异的业务处理功能全都依赖于它们提供的公共技术服务。

让每个业务功能的设计者直接面对裸机、基本操作系统或基本网络
环境来完成软件实现方案是不可思议的。

技术支撑方案应该为多个用例的软件实现提供技术服务,所以它应该成为整个目标软件系统中全局性的公共技术平台。

当用户需求发生变化时,技术支撑方案应具有良好的稳定性。

这就要求软件设计者选用开放性和可扩充性较好的技术支撑方案。

如果目标软件系统的顶层架构采用分层方式,那么技术支撑方案应该位于层次结构中的较低层次。

技术支撑方案的设计一方面取决于目标软件系统对公共技术服务的需求,另一方面取决于设计人员对软件技术手段的把握和选取。

例如,对分布式应用系统而言,设计人员必须了解分布构件技术和基于应用服务器的软件开发技术等。

本节的后续部分将分别以数据持久存储服务、并发与同步控制服务为例探讨技术支撑方案的设计方法,然后介绍技术支撑方案与用例实现方案的融合。

一、数据持久存储服务
设计数据持久存储服务的目的是将目标软件系统中依赖于系统运行环境的数据存取部分与其他部分相分离。

数据存取通过一般的数据管理系统(如文件系统、关系数据库或面向对象数据库)实现,实现细节因数据存储介质的不同种类而异,但这些细节被集中在数据持久存储服务中,系统的其他部分与存储介质的种类和数据存储的实现方法无关。

这样,既有利于软件的扩充、移植和维护,又简化了软件设计、编码和测试的过程。

无论基于哪一种数据管理方法,数据持久存储服务的设计都包括定义数据格式和定义数据存取操作两部分。

定义数据格式。

根据目标软件系统对数据存储的需求,考虑持久存储介质的特性,设计数据的存储格式。

例如,针对文件系统,需要定义用于保存数据的文件类别以及每类文件的记录格式;针对关系数据库,需要定义表格的字段名称、类型、关键字和约束条件等;针对面向对象数据库(Object-Oriented Data Base OODB),数据格式的定义相对简单,因为OODB直接支持对象的存储和读取。

定义数据存取操作。

数据持久存储服务至少包含数据的存储和读取两种操作。

存储操作负责将实体对象中的属性数据写至持久存储介质,读取操作则负责从持久存储介质中的序列化数据恢复对象的属性值。

可以定义适用于所有实体类的存取操作,也可以分别针对不同的实体类定义不同的存取操作。

数据存取操作一般以服务类的形式工业基础系统的其他部分提供数据持久存储服务。

在引久持久存储服务之后,目标软件系统的其他部分对持久存储介质的访问必须通过该服务进行,不能直接访问。

二、并发与同步控制服务
与数据持久存储服务类似,设计并发与同步控制服务的目的是将目标软件系统中依赖于系统运行环境的并发与同步控制部分和其他部分相分离,其他部分中有关并发与同步控制功能的实现均通过该服务来完成。

当然,如果目标软件系统无需考虑并发问题,则可忽略此设计步骤。

一般而言,并发与同步控制服务提供的功能应包括:进程/线程的定义与启动;进程/线程的终止、进程/线程的状态查询、同步点的设置及进程/线程在同步点的信息交换等。

这些功能应封装在服务类之中。

三、技术支撑方案与用例实现方案的融合
技术支撑方案往往包含数个公共技术服务子系统。

这些子系统无论其规模大小和内部复杂度高低,都应该提供数量较少的外部接口。

所有的上层应用功能对公共技术服务的调用均通过访问这些外部接口而实现。

因此,为了事例技术支撑方案和用例实施方案,只需对相应的UML交互图作少许修改,在图中添加必需的公共技术服务子系统接口,让控制类的对象与该接口所代表的公共服务对象进行消息交互。

对数据持久存储服务,与之交互的可以是实体类或者控制类。

至于这些接口在交互图中的布局位置,则依据其所提供服务的性质的不同而有所变化:
(1)先考虑数据持久存储服务。

在引入此服务以后,用例中有关数据持久的实现有两种策略:一是让控制类对象调用此服务实现数据存取,二是让实体类对象直接调用此服务。

在前一种策略下,实体类对象在数据
保存的过程中先向控制类对象提供数据,再由控制类对象调用服务将数据存至持久介质(如数据库、文件等)数据读取的过程则为此过程的逆过程。

在后一策略下,实体类对象负责自己的数据的读取和保存。

相比较而言,后一种策略理为简洁、自然。

对一图8-1-4,如果右侧的边界类与公共数据持久存储服务子系统的接口类的功能多有重叠,则应该考虑将二者合并。

(2)再考虑安全控制服务。

此类服务的子系统接口在顺序图中应位于控制类的紧邻右侧。

(3)最后考虑分布式事务管理服务、并发与同步控制服务及可靠消息服务。

它们的接口类在顺序图中可以位于控制类与右边边界类之间的任意位置,但不应插在两个辅助类或两个实体类的中间。

下面讨论技术支撑方案的类图与迄今获得的其他类图的事例问题。

如果前者比较简单,可以考虑将技术支撑方案的类图直接与其他类图合并,并建立公共技术服务类与其他类之间的必要连接。

此时,有必要在公共技术服务类上以UML构造型进行特殊标识。

如果公共技术服务子系统中包含较多的服务类,它们应单独构成类图,利用UML的包机制进行适当分组,并将这些包置于系统的体系结构图的较低层次(相对而言,应用功能应位于较高层次)。

第三节设计用户界面
需求分析和软件设计阶段都必须考虑人机交互问题。

在需求分析阶段要确定人机交互的属性和外部服务,而在设计阶段要给出有关人机交互的所有系统成份,包括用户如何操作系统、系统如何响应命令和系统显示信息的报表格式等。

用户界面设计的策略与步骤如下:
(1)熟悉用户并对用户分类。

设计人员应深入用户环境,考虑用户需要完成的任务、完成这些任务需要什么工具支持以及这些工具对用户是否适用。

事实上,不同类型的用户要求也不同,一般可按技术熟练程度、工作性质和访问权限对用户进行分类,以便尽量照顾到所有用户的合理要求,并优先满足某些特权用户。

(2)按用户类别分析用户的工作流程与习惯。

在用户分类的基础上,从每类中选取一个用户代表,建立包括下列内容的调查表,并通过对调查结果的分析判断用户地操作界面的需求和喜好:
·姓名
·期望软件用途;
·特征(如年龄、文化程度、限制等);
·主要要求与喜好;
·技术熟练程度;
·任务客观场景描述。

(3)设计命令系统工进行优化。

在设计一个新命令系统时,应尽量遵循用户界面的一般原则和规范,必要时可参考一些优秀的商品软件。

根据用户分析结果确定初步的命令系统,然后再优化。

命令系统既可为若干菜单、菜单栏,也可为一组按钮。

优化命令系统时首先应考虑命令的顺序,一般常用居先,命令的顺序与用户工作习惯一致;其次,根据外部服务之间的聚合关系组织相应的命令,总体功能对应父命令,部分功能对应子命令;然后,充分考虑人类记忆的局限性(即所谓“7±2”原则或“3′3”原则),命令系统最好组织为一棵两层的多叉树;最后,应尽可能减少用户完成一个操作所需的动作(如单击鼠标、拖曳鼠标和敲击键盘等)并为熟练用户提供操作的快捷方式。

(4)设计用户界面的各种细节。

此步骤包括设计一致的用户界面、耗时操作的状态反馈、“undo”机制、帮助用户记忆的操作序列和自封闭的集成环境等。

此类问题的详细讨论见第十二章人机界面设计。

相关文档
最新文档