软件工程复试——十一、面向对象设计

时间:2024-03-19 22:37:35

十一、面向对象设计

面向对象设计概念

​ 设计是把分析阶段得到的需求转变成符合成本和质量要求的、抽象的系统实现方案的过程。从面向对象分析
到面向对象设计是一个逐渐扩充模型的过程,即面向对象设计就是用面向对象观点建立求解域模型的过程。

​ 分类:

  • 系统设计:确定实现系统的策略和目标高层结构

  • 对象设计:确定解空间中的类、关联、接口形式及实现服务的算法。

面向对象设计准则

准则:

  • 模块化(对象就是模块。他是把数据结构和操作这些数据方法紧密的结合在一起所构成的模块)
  • 抽象(支持过程抽象和数据抽象)
  • 信息隐藏(通过封装性实现)
  • 弱耦合(耦合包括交互耦合和继承耦合)
  • 强内聚(服务内聚、类内聚、一般-特殊内聚)
  • 可重用

启发规则

  • 设计结果清晰易懂(遵循用词一致、使用已有协议、减少消息数目、避免模糊定义等因素)
  • 一般-特殊结构深度适当
  • 设计简单的类(避免包括太多属性、有明确的定义、尽量简化对象之间的合作关系、不要提供太多服务)
  • 使用简单的协议
  • 使用简单的服务
  • 把设计变动减至最小

软件重用

重用也叫再用或复用,是指同一事物不作修改或稍加改动就多次重复使用。软件重用可分为以下3个层次:

  • 知识重用;
  • 方法和标准的重用;
  • 软件成分的重用。

重用一般分为以下三个级别

① 代码重用
代码重用是调用库中的模块。
形式:
第一,源代码剪贴
是最原始的重用形式,复制或修改源代码时可能出错,且存在严重的配置管理问题。
第二,源代码包含
配置管理问题有所缓解,所有包含它的程序都必须重新编译。
第三,继承
无须修改已有的代码,就可扩充或具体化在库中找出的类。基本上不存在配置管理问题。
② 设计结果重用
重用某个软件系统的设计模型(求解域模型),有助于把一个应用系统移植到完全不同的软硬件平台上。
③ 分析结果重用
是一种更高级别的重用,重用某个系统的分析模型。特别适用于用户需求未改变,但系统体系结构发生了根
本变化的场合。

可重用的软件成分
  • 项目计划
  • 成本估计
  • 体系结构
  • 需求模型和规格说明
  • 设计
  • 源代码
  • 用户文档和技术文档
  • 用户界面
  • 数据
  • 测试用例

类构件

1、可重用软构件的特点
为使软构件也像硬件集成的电路那样,能在构造各种各样的软件系统时方便地重复使用,就必须使它们满足
下列要求:
① 模块独立性强
具有单一、完整的功能,且经过反复测试被确认是正确的。它应该是一个不受或很少受外界干扰的封装体,
其内部实现在外面是不可见的。
② 具有高度可塑性
可重用的软构件必须具有高度可裁剪性,即必须提供为适应特定需求而扩充或修改已有构件的机制,而且所
提供的机制必须使用起来简单方便。
③ 接口清晰、简明、可靠
软构件应该提供清晰、简明、可靠的对外接口,而且还应该有详尽的文档说明,以方便用户使用。

2、类构建的重用方式

① 实例重用
除了用已有的类为样板直接创建该类的实例之外,还可以用几个简单的对象作为类的成员创建出一个更复杂
的类。
② 继承重用
当己有的类构件不能通过实例重用方式满足当前系统的需求时,利用继承机制从巳有类派生出符合需要的子
类,是安全修改巳有的类构件并获得可在当前系统中使用的类构件的有效手段。
③ 多态重用
在设计类构件时应把注意力集中在下列这些可能妨碍重用的操作上:
a. 与表示方法有关的操作。
b. 与数据结构、数据大小等因素有关的操作。
c. 与外部设备有关的操作。
d. 实现算法在将来可能会改变的核心操作。

3、软件重用的效益

  • 质量(重用代码质量高!)
  • 生产率(速度当然变快了)
  • 成本(直接拿来用比较省钱啊!)

系统分解

​ 在设计比较复杂的应用系统时,先把系统分解成若干个较小部分,然后分别设计每个部分。这样做有利于降低设计的难度,有利于分工协作,也有利于维护人员对系统理解和维护。

子系统

系统的主要组成部分称为子系统,通常根据所提供的功能来划分子系统。

划分原则:
① 根据所提供的功能来划分子系统,子系统数目应该与系统规模基本匹配。
② 各个子系统之间应该具有尽可能简单、明确的接口。
③ 应该尽量减少子系统彼此间的依赖性。

面向对象模型

​ 面向对象设计模型由主题、类与对象、结构、属性、服务5个层次组成。这5个层次一层比一层表示的细
节更多,可以把这5个层次想象为整个模型的水平切片。
​ 面向对象设计模型在逻辑上都由4大部分组成,分别对应于组成目标系统的4个子系统,即问题域子系统、
人机交互子系统、任务管理子系统和数据管理子系统。

下图是典型的面向对象模型
软件工程复试——十一、面向对象设计

子系统间交互方式
在软件系统中,子系统之间的交互有两种可能的方式,分别是客户一供应商(Client-supplier)关系和平等伙
伴(peer-to-peer)关系。

① 客户一供应商关系
作为“客户"的子系统调用作为“供应商”的子系统,后者完成某些服务工作并返回结果。作为客户的子系
统必须了解作为供应商的子系统的接口,后者却无须了解前者的接口。
② 平等伙伴关系
每个子系统都可能调用其他子系统,每个子系统都必须了解其他子系统的接口。由于各个子系统需要相互了
解对方的接口,子系统之间的交互复杂,且还可能存在通信环路。

组织系统的两种方案

把子系统组件为完整系统时,一般使用水平层次组织和垂直块组织两种方案。

①层次组织
a. 定义
软件系统组织成一个层次系统,每层是一个子系统。上层在下层的基础上建立,下层为实现上层功能而提供必要的服务。每一层内所包含的对象,彼此间相互独立,而处于不同层次上的对象,彼此间有关联。在上、下层之间存在客户一供应商关系。低层子系统提供服务,上层子系统使用下层提供的服务。
b. 模式分类
第一,封闭式
每层子系统仅仅使用其直接下层提供的服务。降低了各层次之间的相互依赖性,更容易理解和修改。
第二,开放式
子系统可以使用处于其下面的任何一层子系统所提供的服务。优点是减少了需要在每层重新定义的服务数
目,使系统更高效更紧凑。但其不符合信息隐藏原则。

② 块状组织
把软件系统垂直地分解成若干个相对独立的、弱耦合的子系统,一个子系统相当于一块,每块提供一种类型
的服务。
③ 层次和块的组合
当混合使用层次结构和块状结构时,同一层次可以由若干块组成,而同一块也可以分为若干层。
④ 设计系统的拓扑结构
典型的拓扑结构有管道形、树形、星形等。应釆用与问题结构相适应的、尽可能简单的拓扑结构,以减少子
系统之间的交互数量。

设计问题域子系统

1.概念
(1) 面向对象分析所得出的问题域精确模型,为设计问题域子系统建立了完整的框架。
(2) 保持面向对象分析所建立的问题域结构。
(3) 面向对象设计仅需从实现角度对问题域模型做一些补充或修改。
(4) 问题域子系统过分复杂庞大时,应该把它进一步分解成若干个更小的子系统。

2、对问题域模型进行处理

  • 调整需求

  • 重用已有类

  • 把问题域类组合在一起

  • 增添一般化类以建立协议

  • 调整继承层次

    ​ ①多重继承机制
    ​ 使用多重继承机制时,应该避免出现属性及服务的命名冲突。

    ​ ②单继承机制
    ​ 使用单重继承机制时,必须把面向对象分析模型中的多重继承结构转换成单继承结构。

设计人机交互系统

​ 在面向对象设计过程中,对系统的人机交互子系统进行详细设计,以确定人机交互的细节,其中包括指定窗
口和报表的形式、设计命令层次等项内容。

设计策略

  • 分类用户(把将来可能与系统交互的用户进行分类)
  • 描述用户(了解、记录每类使用系统用户的情况)
  • 设计命令层次(研究现有的人机交互含义和准则、确定初始的命令层次、精化命令层次)
  • 设计人机交互类

设计任务管理子系统

1.设计的必要性
(1) 许多对象之间往往存在相互依赖关系。
(2) 在实际使用的硬件中,可能仅由一个处理器支持多个对象。

步骤:

1、分析并发性

如果两个对象彼此间不存在交互,或它们同时接受事件,则它们在本质上是并发的。

分析步骤:

a. 通过面向对象分析建立起来的动态模型,是分析并发性的主要依据。
b. 通过检查各个对象的状态图及它们之间交换的事件,能够把若干个非并发的对象归并到一条控制线中。

2、设计任务管理子系统
  • 确定事件驱动型任务(主要是完成通信工作)
  • 确定时钟驱动型任务(每隔一定时间就被触发)
  • 确定优先任务(优先任务可用满足高优先级或低优先级的处理请求)
  • 确定关键任务(其中包含有系统成功或失败的关键处理)
  • 确定协调任务(当系统中存在3个以上任务时,就应该增加一个协调任务以将不同任务间的协调封装起来)
  • 尽量减少任务数
  • 确定资源需求

设计数据管理系统

​ 数据管理子系统是系统存储或检索对象的基本设施,它建立在某种数据存储管理系统之上,并且隔离了数据
存储管理模式的影响。

一般的管理系统有以下几种:

1、文件管理系统

文件管理系统是操作系统的一个组成部分,使用它长期保存数据具有成本低和简单的优点。但是其文件操作级别低,为提供适当的抽象级别还必须写额外代码。

2、关系数据库管理系统

优点:

a. 理论基础坚实
b. 提供了各种最基本的数据管理功能,例如中断恢复,多用户共享,多应用共享,完整性,事务支持等
c. 为多种应用提供了一致的接口
d. 标准化的语言

缺点:

a. 运行开销大:即使完成简单的事务,也需要较长的时间。
b. 不能满足高级应用的需求:关系数据库管理系统是为商务应用服务的,商务应用中数据量虽大但数据结
构却比较简单。
c. 与程序设计语言的连接不自然:SQL语言支持面向集合的操作,是一种非过程化的语言;然而大多数程
序设计语言本质上却是过程性的,每次只能处理一个记录。

3、面向对象数据库管理系统

① 扩展的关系数据库管理系统
在关系数据库的基础上,增加了抽象数据类型和继承机制,此外还增加了创建及管理类和对象的通用服务。
② 扩展的面向对象程序设计语言
扩充了面向对象程序设计语言的语法和功能,增加了在数据库中存储和管理对象的机制。可以使用统一的面
向对象观点进行设计,不需要区分存储数据结构和程序数据结构。

设计数据管理子系统

设计数据管理子系统既要设计数据的格式也要设计相应的服务。

书上278页有很多例子,各位自己看一看。

设计类中的服务

确定类中服务

(1) 确定服务的总体思想
① 对象模型是进行对象设计的基本框架。必须把动态模型中对象的行为以及功能模型中的数据处理转换成由
适当的类所提供的服务。
② 动态模型中状态图中的状态转换执行对象服务的结果。
③ 功能模型指明了系统必须提供的服务。
(2) 确定操作目标对象的启发规则
① 如果某个处理的功能是从输入流中抽取一个值,则该输入流就是目标对象。
② 如果某个处理具有类型相同的输入流和输出流,而且输出流实质上是输入流的另一种形式,则该输入输出
流就是目标对象。
③ 如果某个处理从多个输入流得出输出值,则该处理是输出类中定义的一个服务。
④ 如果某个处理把对输入流处理的结果输出给数据存储或动作对象,则该数据存储或动作对象就是目标对
象。
(3) 确定处理归属的启发规则
① 如果处理影响或修改了一个对象,则最好把该处理与处理的目标联系在一起。
② 考察处理涉及的对象类及这些类之间的关联,从中找出处于中心地位的类。

设计实现服务的方法

主要完成以下工作:

  • 设计实现服务的算法

    主要考虑以下因素:

    • 算法复杂度
    • 容易实现容易理解
    • 易修改
  • 选择数据结构

  • 算法与数据结构的关系

    • 分析问题寻找数据特点,提炼出所有可行有效的算法
    • 定义与所提炼算法相关联的数据结构
    • 依据此数据结构进行详细设计
    • 进行一定规模的实验和评测
    • 确定最佳设计
  • 定义内部类和内部操作

设计关联

在对象模型中,关联是联结不同对象的纽带,它指定了对象相互间的访问路径。

关联的遍历一般分为单向遍历和双向遍历。

实现单项关联

用指针可以方便的实现单向关联。下面是用指针实现单向关联具体例子。

其中a为关联b为实现

单向关联:

软件工程复试——十一、面向对象设计

实现双向关联

① 只用属性实现一个方向的关联
如果两个方向遍历的频度相差很大,而且需要尽量减少存储开销和修改时的开销,则这是一种很有效的实现
双向关联的方法。
② 两个方向的关联都用属性实现
这种方法能实现快速访问。当访问次数远远多于修改次数时,这种实现方法很有效。如下图所示

软件工程复试——十一、面向对象设计
]③ 用独立的关联对象实现双向关联
关联对象不属于相互关联的任何一个类,它是独立的关联类的实例,如下图所示。

软件工程复试——十一、面向对象设计
关联对象的实现

用一个关联类来保存描述关联性质的信息,关联中的每个连接对应关联类的一个对象。

设计优化

首先要确定各项指标的相对重要性(优先级)

在效率和清晰度之间寻求适当的折中方案。在折中方案中设置的优先级应当是模糊的。

提升效率的几项技术

  • 增加冗余关联以提高访问效率
  • 调整查询次序
  • 保留派生属性

调整继承关系

继承关系能够为一个类族定义一个协议,并能在类之间实现代码共享以减少冗余。在面向对象设计中,建立良好的类继承非常重要。

①抽象与具体
在设计类继承时,很少使用纯粹自顶向下的方法,通常的做法如下:
a. 创建满足具体用途的类,然后对它们进行归纳。
b. 归纳出一些通用的类以后,根据需要再派生出具体类。
c. 进行一些具体化的工作后,再次归纳。

各位可以去看以下书上285页的例子以加深理解

② 为提高继承程度而修改类定义
在一组相似的类中存在公共的属性和公共的行为时,可以把这些公共的属性和行为抽取出来放在一个共同的
祖先类中,供其子类继承。。在对现有类进行归纳的时候,要注意下述两点:
a. 不能违背领域知识和常识。
b. 应该确保现有类的协议不变。
③ 利用委托实现行为共享
仅当存在真实的一般一特殊关系(子类确实是父类的一种特殊形式)时,利用继承机制实现行为共享才是合
理的。

课后题

1、

(1) 模块化
对象是面向对象软件系统中的模块,它是把数据结构和操作这些数据的方法紧密地结合在一起所构成的模
块。
(2) 抽象
面向对象的程序设计语言不仅支持过程抽象,而且支持数据抽象,对象类实际上是具有继承机制的抽象数据
类型。
(3) 信息隐藏
在面向对象的软件中,信息隐藏通过对象的封装来实现,即类结构分离了接口与实现,从而支持了信息隐藏。
(4) 弱耦合
① 交互耦合
对象间的耦合通过消息连接来实现,则这种耦合是交互耦合。要使交互耦合尽可能松散。
② 继承耦合
继承是一般类与特殊类之间耦合的一种形式。通过继承关系结合起来的基类和派生类构成了系统中粒度更大
的模块,因此,它们彼此之间应该结合得越紧密越好。
(5) 强内聚
① 服务内聚
一个服务应该完成一个且仅完成一个功能。
② 类内聚
设计类的准则是,一个类应该只有一个用途,它的属性和服务应该是高内聚的。
③ 一般一特殊内聚
设计出的一般一特殊结构应该是对相应的领域知识的正确抽取。紧密的继承耦合与高度的一般一特殊内聚是
一致的。
(6) 可重用
软件重用是提高软件开发生产率和目标系统质量的重要途径。重用基本上从设计阶段开始。重用有两方面的
含义:
① 尽量使用已有的类。
② 如果需要创建新类,则在设计这些新类的协议时应该考虑将来的可重复使用性。

2、

答:(1)有助于提高面向对象设计质量的主要启发规则如下所述:
①设计结果应该清晰易懂
a.用词一致。

b.使用巳有的协议。
C.减少消息模式的数目。
d.避免模糊的定义。
② 一般一特殊结构的深度应适当
③ 设计简单的类
a. 不要包含过多的属性。
b. 有明确的定义。为使类的定义明确,分配给每个类的任务应该简单。
c. 简化对象之间的合作关系。
d. 不要提供太多的服务。
④ 使用简单的协议
⑤ 使用简单的服务
⑥ 把设计变动减至最小
(2)启发规则的必要性
人们使用面向对象方法学开发软件的历史虽然不长,但也积累了一些经验。总结这些经验得出了几条启发规
则,它们往往能帮助软件开发人员提高面向对象设计的质量。

3、

答:(1)可重用的软构件应具备的特点:
① 模块独立性强。
② 具有高度可塑性。
③ 接口清晰、简明、可靠。
(2)类构件的重用方式:
① 实例重用。
② 继承重用。
协议时应该考虑将来的可重复使用性。