800 likes | 946 Views
第七章 面向对象的设计方法 . 设计用例实现方案 设计技术支撑方案 设计用户界面 精化设计模型. 面向对象的设计方法. 基于 UML 的面向对象设计方法将分析模型转换为设计模型。 面向对象 : 分析模型 --- 顶层架构图、用例与用例图、领域概念模型构成。 设计模型 ----- 以包图表示的软件体系结构图 以交互图表示的用例实现图 完整、精确的类图
E N D
第七章 面向对象的设计方法 • 设计用例实现方案 • 设计技术支撑方案 • 设计用户界面 • 精化设计模型
面向对象的设计方法 • 基于UML的面向对象设计方法将分析模型转换为设计模型。 • 面向对象: 分析模型---顶层架构图、用例与用例图、领域概念模型构成。 设计模型----- 以包图表示的软件体系结构图 以交互图表示的用例实现图 完整、精确的类图 复杂对象的状态图 描述流程化处理过程的活动图
7.1 设计用例实现方案 本节介绍UML交互图的语言机制和用例实现方案的设计方法。 • UML的交互图包括顺序图和协作图,适于用例实现方案的表示。 • 用例实现方案的设计方法有三个步骤: (1) 提取边界类、实体类和控制类; (2) 构造交互图; (3) 根据交互图精化类图。
UML四种类型的消息 (1) 简单消息(Simple Message) 以一种简单、抽象的函数表示对象之间的信息传递,不考虑通信过程的内部细节。简单消息在UML顺序图中用普通的有向箭头表示。 (2) 同步消息(Synchronous Message) 消息源发出消息后必须等待消息处理过程完毕并返回处理结果后,消息源才可继续执行后续操作。前面所述的自调用消息应该是同步的。同步消息的表示图元与简单消息相同,这表明UML在缺省情形下认为简单消息即为同步消息。
UML四种类型的消息 (3) 异步消息(Asynchronous Message) 表示,消息源发出消息后不必等待消息处理过程的返回,即可继续执行自己的后续操作。异步消息主要用于描述实时系统中的并发行为。异步消息在UML顺序图中用一种特别的单向箭头表示 (4) 返回消息(Return message) 表示前面发送的消息的处理过程完结之后的返回结果。返回消息应该是同步的。在许多情况下,可以隐藏返回消息,但也可显式标出返回消息以示强调。返回消息用虚线有向箭头表示 一个对象可以通过发送标准消息“new”来创建另一个对象。当一个对象被删除或自我删除时,该对象的生命线上的相应时间点应该用叉号(对象生命线终结符)标识。
7.1.2 协作图 协作图用于描述相互合作的对象间的交互关系和链接关系。虽然顺序图和协作图都用来描述对象间的交互关系,但它们的侧重点不一样。顺序图强调消息交互的时间序,协作图则强调交互对象间的静态链接关系。 从外观看,协作图并不采用单独的维度来表示时间推移,因此,协作图中的对象可以在二维平面中自由占位。对象之间的链接用于表示消息传递通道,消息标示于链接之上,消息的箭头指明消息的传递方向。在协作图中,消息的描述内容包含名称、参数、返回值以及序列号,返回值和序列号是可选的。
协作图 虽然协作图不强调消息传递的时间序,但借助于序列号可以表达时间序,序列号较大的消息发生较晚。 消息序列号可以采用线性编号,但采用适当的多级编号会使消息之间的结构关系更清晰。 如果一个对象在消息的交互过程中被创建,则可在对象名称之后标以{new}。类似地,如果一个对象在交互期间被删除,则可在对象名称之后标以{destroy}。
典型的协作图 例 • “1.1 msg2”表明msg2是“对象1”为了处理“1. msg1”而发送的第一条消息 • “1.2 msg4”是“对象1”为了处理“1. msg1”而发送的第二条消息 • “1.1.1 msg3”表明msg3是“对象2”为了处理“1.1 msg2”而发送的第一条消息,依此类推。
7.1.3 提取边界类、实体类和控制类 边界类描述目标软件系统与外部环境的交互,主要任务: (1) 界面控制:包括输入数据的格式及内容转换,输出结果的呈现,软件运行过程中界面的变化与切换等。 (2) 外部接口:实现目标软件系统与外部系统或外部设备之间的信息交流和互操作。主要关注跨越目标软件系统边界的通信协议。 (3) 环境隔离:将目标软件系统与操作系统、数据库管理系统、应用服务器中间件等环境软件进行交互的功能与特性封装于边界类之中,使目标软件系统的其余部分尽可能地独立于环境软件。 在UML类图中,边界类往往附加UML构造型《boundary》作为特别标识。
提取边界类、实体类和控制类 例如,“家庭保安系统”中的边界类有“输入键盘接口类”、“传感器接口类”、“警报器接口类”、“报警电话接口类”和“显示面板接口类”。 实体类表示目标软件系统中具有持久意义的信息项及其操作。实体类的操作具有“内向收敛”特征,它们仅向目标软件系统的其余部分提供读、写信息项内容的必要的操作接口,并不涉及业务逻辑处理。实体类的UML构造型为《entity》。 例如,“家庭保安系统”中的“异常事件”为实体类。
提取边界类、实体类和控制类 控制类作为完成用例任务的责任承担者,协调、控制其他类共同完成用例规定的功能或行为。对于比较复杂的用例,控制类通常并不处理具体的任务细节,但是它应知道如何分解任务,如何将子任务分派给适当的辅助类,如何在辅助类之间进行消息传递和协调。控制类的UML构造型为《control》。 例如,“家庭保安系统”中,“用户命令处理器”和“监测器”均为控制类。
提取边界类、实体类和控制类 在讨论了边界类、实体类和控制类的基本概念之后,下面介绍如何从分析模型中的用例描述和领域概念模型出发获取这些类。 通常情况下,执行者与用例之间的一种通信连接对应一个边界类。但是,如果两个以上的用例与同一执行者交互,并且这些交互具有共同的行为、完成相同或类似的任务,就可以考虑用同一边界类实现用例与执行者之间的交互。这就意味着边界类的作用范围可以超越单个用例。
提取边界类、实体类和控制类 • 实体类源于领域概念模型。有时也需要认真研读用例描述,从中发掘具有持久意义的信息项。 • 如果执行者的属性需要持久保存,也可以建立相应于执行者的实体类。 • 假设一个实体类A仅仅被系统中的另一个类B引用,并且系统勿需关心A的行为特征,那么,为了简化设计模型,应将A中信息项直接作为B的属性。 • 如果A被系统中的多个类引用,或者A具有不容忽略的行为特征,那么应将A作为独立的实体类。
提取边界类、实体类和控制类 • 一个用例通常对应一个控制类。 • 如果不同用例的任务有较多类似之处,也可以考虑在多个用例的实现方案中共享同一控制类,此种情况应审慎对待,不同用例所需要的控制、协调行为往往会有差异。 • 对于那些事件流非常简单的用例,可以不设独立的控制类,直接在边界类中设置控制、协调功能,边界类在实体类的帮助下完成用例要求的功能及行为。
7.1.4 构造交互图 在标识边界类、实体类和控制类之后,接下来的任务是,将分析模型中的用例描述转化成UML交互图,以交互图作为用例的精确实现方案。 • 用例描述中已包含事件流说明。 • 事件流中的事件应直接对应于交互图中的消息,而事件间的先后关系体现为交互图中的时序,对消息的响应则构成消息接收者的职责。 这种职责在后续的设计活动中将被确立为类的方法。
构造交互图 • 对于比较复杂的用例,仅仅依靠控制类、边界类和实体类会使单个控制类过于庞大、复杂,它既承担控制、协调的任务,又承担复杂的计算任务。 • 在设计复杂用例的实施方案时,应考虑为控制类设置一些独立的辅助类,让控制类将一些任务委托给辅助类完成。 如,在 “家庭保安系统”类图中,“系统配置管理器”和“日志管理器”就是这种意义上的辅助类。
构造交互图 UML顺序图的横向排列次序 • 用例的主动执行者 • 用户界面的边界类 • 控制类 • 实体类和辅助类 • 外部接口和环境隔离层的边界类 • 目标软件系统的边界之外的被动执行者 按此布局,在顺序图中不应该出现穿越控制类生命线的消息,即,主动执行者向界面类发出命令,界面类将命令进行适当转换后传送至控制类,控制类通过消息请求辅助类、实体类的帮助,协调、控制它们共同完成来自主动执行者的命令。
构造交互图 • 控制类或辅助类可以向右侧的边界类发送消息,将信息或外部处理请求由边界类传向外部系统(被动执行者)。 • 在用例描述中,许多用例除主事件流外,往往还包含备选事件流,以说明在某些特殊或者异常情况下的事件和响应动作序列。为易于理解,在设计模型中应该用分离的UML交互图分别表示事件流和每个备选事件流。 • 按照上述布局规则绘制的典型的顺序图如图10.4所示
构造协作图 由于顺序图能够非常直观地表达事件(消息)的时序,所以它比协作图更多地用于描述用例的实现方案。但是,当需要强调类之间的联系或连接时,就需要绘制协作图。 协作图的布局规则 • 控制类位于中心 • 主动执行者和作为用户界面的边界类位于左上方 • 作为外部接口和环境隔离层的边界类位于右上方 • 辅助类和实体类分别位于控制类的左下、右下方。 • 按照此布局规则绘制的典型的协作图如图10.5所示。
例 家庭保安系统 在“家庭保安系统”中,用例“传感器监测”和“命令处理”的实现方案分别见图10.6和图10.7。 为简洁,图10.6和图10.7未表示这两个用例中的日志功能,图10.7也未考虑配置命令的处理。
7.1.5 精化类图 在UML交互图中,对每个类的对象都规定了它必须响应的消息以及类的对象之间的消息传递通道。前者对应于类的操作,后者则对应于类之间的连接关系。因此,可以利用交互图精化分析模型中的类图,将交互图中出现的新类添加到原有类图中,并且对相关的类进行精化,定义其属性和操作。 原则上,每个类都应该有一个操作来响应交互图中指向其对象的那条消息。但是,这并不意味着消息与操作一定会一一对应,因为类的一个操作可能具有响应多条消息的能力。同理,两个类之间的一条连接关系也可以为多条消息提供传递通道。为了简化设计模型,也为了提高重用程度,设计人员应该尽量使用已有的操作来响应新消息,并尽量使用已存在的连接路径作为消息传递的通道。如果两个类之间存在明确、自然的聚合或组合关系,则可以在类图中直接用相应的UML图元符号表示类间的聚合和组成关系,这两个关系均可提供消息传递通道。
精化类图 接下来讨论如何根据交互图确立类的属性。类的操作完成消息响应责任的能力,来源于两方面的知识,一是类本身具有的信息,即类的属性,二是类能够找到的其他类,通过其他类协助其完成消息响应。在综合考虑这两个因素之后,类的操作应该明确哪些子任务可通过消息传递路径委托给其他类完成,哪些子任务必须由自身完成。根据后一种子任务的需要,结合领域和业务知识即可推导出类应具有的属性。 在图6.16的基础上,得出“家庭保安系统”的类图如图10.8所示。为简洁见,图10.8仅标出控制类“监测器”和“用户命令处理器”的方法,以及实体类“异常事件”的属性,有兴趣的读者可自行添加其余的属性和方法。
7.2 设计技术支撑方案 在许多软件项目中,应用功能往往都需要一组技术支撑机制为其提供服务。例如,对分布式应用软件(包括电子商务应用、企业ERP系统等)而言,需要数据持久存储服务、安全控制服务、分布式事务管理服务、并发与同步控制服务、可靠消息服务等。这些技术支撑设施并非业务需求的直接组成部分,但形态各异的业务处理功能全都有赖于它们提供的公共技术服务。让每个业务功能的设计者直接面对裸机、基本操作系统或基本网络环境来完成软件实现方案,那是不可思议的。
设计技术支撑方案 • 技术支撑方案应该为多个用例的软件实现提供技术服务,所以,它应该成为整个目标软件系统中全局性的公共技术平台。 • 当用户需求发生变化时,技术支撑方案应具有良好的稳定性。这就要求软件设计者选用开放性和可扩充性较好的技术支撑方案。 • 如果目标软件系统的顶层架构采用分层方式,那么,技术支撑方案应该位于层次结构中的较低层次。
设计技术支撑方案 技术支撑方案的设计取决于 • 目标软件系统对公共技术服务的需求 • 设计人员对软件技术手段的把握和选取 如,对分布式应用系统,设计人员必须了解分布构件技术、基于应用服务器的软件开发技术等。 本节的后续部分以数据持久存储服务、并发与同步控制服务为例,探讨技术支撑方案的设计方法,最后介绍技术支撑方案与用例实施方案的融合。
7.2.1 数据持久存储服务 设计数据持久存储服务的目的是,将目标软件系统中依赖于系统运行环境的数据存取部分与其他部分分离。 数据存取通过一般的数据管理系统(如文件系统、关系数据库或面向对象数据库)实现,实现细节因数据存储介质的种类而异,但这些细节被集中在数据持久存储服务中,系统的其他部分与存储介质的种类和数据存储的实现方法无关。这样既有利于软件的扩充、移植和维护,又简化了软件设计、编码和测试的过程。
数据持久存储服务 数据持久存储服务的设计包括,定义数据格式和定义数据存取操作两部分。 (1) 定义数据格式。 根据目标软件系统对数据存储的需求,考虑持久存储介质的特性,设计数据的存储格式。 如,针对文件系统,需要定义用于保存数据的文件类别、每类文件的记录格式; 针对关系数据库,需要定义表格的字段名称、类型、关键字、约束条件等; 针对面向对象数据库(OODB),数据格式的定义相对简单,因为OODB直接支持对象的存储和读取。
数据持久存储服务 (2) 定义数据存取操作。 数据持久存储服务至少包含数据的存储和读取两种操作。 • 存储操作负责将实体对象中的属性数据写至持久存储介质 • 读取操作则负责从持久存储介质中的序列化数据恢复对象的属性值。 可以定义适用于所有实体类的存取操作,也可以分别针对不同的实体类定义不同的存取操作。 数据存取操作一般以服务类的形式为系统的其他部分提供数据持久存储服务。 在引入持久存储服务之后,目标软件系统的其他部分对持久存储介质的访问必须通过该服务进行,不能直接访问。
7.2.2 并发与同步控制服务 设计并发与同步控制服务的目的是,将目标软件系统中依赖于系统运行环境的并发与同步控制部分和其他部分分离,其他部分中有关并发与同步控制功能的实现均通过该服务来完成。 并发与同步控制服务提供的功能包括: (1)进程/线程的定义与启动; (2)进程/线程的终止; (3)进程/线程的状态查询; (4)同步点的设置及进程/线程在同步点的信息交换,等。 这些功能应封装在服务类之中。
7.2.3 技术支撑方案与用例 实现方案的融合 技术支撑方案往往包含数个公共技术服务子系统。这些子系统无论其规模大小和内部复杂度高低,都应该提供数量较少的外部接口。 • 所有的上层应用功能对公共技术服务的调用均通过访问这些外部接口而实现。 • 为了融合技术支撑方案和用例实施方案,只需要对相应的UML交互图中添加必需的公共技术服务子系统接口,让控制类的对象与该接口所代表的公共服务对象进行消息交互。 • 对于数据持久存储服务,与之交互的可以是实体类或者控制类。至于这些接口在交互图中的布局位置,则依其所提供服务的性质的不同而有所变化:
技术支撑方案与用例实现方案的融合 (1) 先考虑数据持久存储服务。 在引入此服务以后,用例中有关数据持久的实现有两种策略: 一是让控制类对象调用此服务实现数据存取 实体类对象在数据保存的过程中先向控制类对象提供数据,再由控制类对象调用服务将数据存至持久介质(如数据库、文件等),数据读取的过程则为此过程的逆过程。 二是让实体类对象直接调用此服务 实体类对象负责自己的数据的读取和保存。相比较而言,后者更为简洁、自然。对于图10.4,如果右侧的边界类与公共数据持久存储服务子系统的接口类的功能多有重叠,应该考虑将二者合并。
技术支撑方案与用例实现方案的融合 (2) 再考虑安全控制服务。 此类服务的子系统接口在顺序图中应位于控制类的紧邻右侧。 (3) 最后考虑分布式事务管理服务、并发与同步控制服务及可靠消息服务。 它们的接口类在顺序图中可以位于控制类与右边边界类之间的任意位置,但不应插入两个辅助类或两个实体类中间。
技术支撑方案与用例实现方案的融合 现在讨论技术支撑方案之类图与迄今获得的其他类图的融合问题。如果前者比较简单,可以考虑将技术支撑方案的类图直接与其他类图合并,并建立公共技术服务类与其他类之间的必要连接。此时,有必要在公共技术服务类上以UML构造型进行特殊标识。如果公共技术服务子系统中包含较多的服务类,它们应单独构成类图,利用UML的包机制进行适当分组,并将这些包置于系统的体系结构图中的较低层次(相对而言,应用功能应位于较高层次)。
7.3 设计用户界面 需求分析和软件设计阶段都必须考虑人机交互问题。 • 需求分析阶段要确定人机交互的 属性和外部服务 • 设计阶段要给出有关人机交互的所有系统成份,包括:用户如何操作 系统、系统如何响应命令、系统显示信息的报表格式等。
HIC设计的策略与步骤为: (1) 熟悉用户并对用户分类。设计人员应深入用户环境,考虑用户需要完成的任务、完成这些任务需要什么工具支持以及这些工具对用户是否适用。 不同类型的用户要求不同,一般可按技术熟练程度、 工作性质和访问权限对用户分类,以便尽量照顾到所有用户的合理要求,并优先满足某些特权用户。 (2) 按用户类别分析用户工作流程与习惯。在用户分类的基础上,从每类中选取一个用户代表,建立包括下列内容的调查表,并通过对调查结果的分析判断用户对操作界面的需求和爱好: ·姓名 ·期望软件用途 ·特征(年龄、文化程度、限制等) ·主要要求与爱好 ·技术熟练程度 ·任务客观场景描述 设计用户界面
设计用户界面 (3) 设计并优化命令系统。 • 在设计一个新命令系统时,应尽量遵循用户界面的一般原则和规范,必要时参考一些优秀的商品软件。 • 根据用户分析结果确定初步的命令系统,然后再优化。 • 命令系统既可为若干菜单、菜单栏,亦可为一组按钮。
设计用户界面 优化命令系统 • 应考虑命令的顺序,一般常用命令居先,命令的顺序与用户工作习惯保持一致; • 根据外部服务之间的聚合关系组织相应的命令,总体功能对应父命令,部分功能对应子命令; • 充分考虑人类记忆的局限性(即所谓“7±2 ”原则或“3×3”原则),命令系统最好组织为一棵两层的多叉树; • 应尽可能减少用户完成一个操作所需的动作(如点按、拖曳和击键等),并为熟练用户提供操作捷径
设计用户界面 (4) 设计用户界面的各种细节。此步骤包括:设计一致的用户界面风格;耗时操作的状态反馈;“undo”机制;帮助用户记忆操作序列;自封闭的集成环境等。此类问题的详细讨论见“第十二章 人机界面设计”。
设计用户界面 (5) 增加用户界面专用的类与对象。用户界面专用类的设计与所选用的图形用户界面(GUI)工具或者支持环境有关。一般而言,需要为窗口、菜单、对话框等界面元素定义相应的类,这些类往往继承自GUI工具或者支持环境提供的类库中的父类。最后,还需要针对每个与用户命令处理相关的界面类,定义控制设计模型中的其他类的方法。 (6) 利用快速原型演示,改进界面设计。为人机交互部分构造原型,是界面设计的基本技术之一。为用户演示界面原型,让他们直观感受目标软件系统的使用方法,并评判系统是否功能齐全、方便好用。
7.4 精化设计模型 经过前面的分析和设计步骤,设计模型已相当丰富,包含了较完整的静态结构模型(顶层架构图、类图)和动态行为模型(交互图)。 现在有必要对这些模型再进行分析、优化,以生成高质量的设计模型,为后续的实现阶段奠定坚实基础。
精化设计模型 设计模型精化的任务 (1) 以顶层架构图为基础,精化目标软件系统的体系结构。 (2) 精化类之间的关系。 (3) 精化类的属性和操作。 (4) 针对具有明显状态转换特征的类,设计状态图。 (5) 针对比较复杂的类方法,设计活动图。 本节首先介绍UML状态图,然后依次介绍完成上述任务的方法。
7.4.1 精化体系结构 精化体系结构的目的是,寻找一种包的划分方案,使得每个包直接包含的类的数量适中,包的边界清晰、自然,并且包间的耦合度较低。 在包图中,包间耦合度取决于包间依赖关系,而依赖关系又取决于分属于两个包的类之间的关系。 类之间的耦合程度(从高到低)排列: (1)继承关系。 (2)构成关系。 (3)聚合关系。 (4)关联关系。 (5)依赖关系。 (6)两个类的对象受同一执行者变化的影响。