面向对象设计
Created: 2024-03-05 Tue 16:42
由于在类中封装了 属性 和 方法 ,因此在类设计中已经包含了传统方法中的 过程设计 。
Figure 1: 系统环境图
每个 外部实体 都通过某一 接口 (带阴影的小矩形)与 目标系统 进行通信。
根据客户的需求选择 体系结构 风格,之后对可选的体系结构 风格 或 模式 进行分析。 以导出最适合 客户需求 和 质量属性 的结构。
体系结构设计 往往要经过多次 反复迭代 和 求精 才能得到满意的结果。
对于 面向对象的系统 ,典型的子系统有:
对象设计 以问题领域的对象设计为核心,其结果是一个详细的 对象模型 。
体系结构设计 描述了建立计算机系统所需的 数据结构 和 程序构件 。
在 面向对象 的程序设计中, 类 和 接口 是程序的基本组成单元。
在计算机程序中,要设计和实现所有类都具有唯一的名字, 在 不同的阶段 或从 不同的角度 可以将它们称为
设计类 、 实现类 、 系统类 或 应用类 等。
%%{init: { 'theme': 'forest', 'fontFamily': 'DejaVu Sans' }}%%
classDiagram
class CActioner {
emp:EEmployee
do1()
}
class EEmployee {
do3()
}
class EOutMessage {
emp:EEmployee
do2()
}
CActioner "0..n" --> "0..1" EEmployee
CActioner ..> EEmployee
EOutMessage "0..n" --> "0..1" EEmployee
EOutMessage ..> EEmployee
Figure 2: 交互依赖性
public class CActioner {
EEmployee emp;
public void do1() {
emp.do3();
}}
public class EOutMessage {
EEmployee emp;
public void do2() {
emp.do3();
}}
接口 与 抽象类 有相似之处。
Class1
实现了 Interface1
和 Interface2
,而 Class2
只实现了 Interface2
。
%%{init: { 'theme': 'forest', 'fontFamily': 'DejaVu Sans' }}%%
classDiagram
class Interface1 {
<<interface>>
a1
op1()
}
class Interface2 {
<<interface>>
a2
op2()
}
class Class1
class Class2
Interface1 <|.. Class1
Interface2 <|.. Class1
Interface2 <|.. Class2
Figure 3: 实现依赖性
%%{init: { 'theme': 'forest', 'fontFamily': 'DejaVu Sans' }}%%
classDiagram
class Interface1 {
<<interface>>
a1
op1()
}
class Interface2 {
<<interface>>
a2
op2()
}
class Class1 {
do1()
}
Interface1 --> Interface2 : 《uses》
Interface1 <-- Class1 : 《uses》
Figure 4: 使用依赖性
public class Class1 {
Interface1 myInterface;
public void do1() {
myInterface.op1();
}
}
Class1
使用 Interface1
, Interface1
使用 Interface2
。
在Java语言中,
当系统中涉及的类的数量比较多时,往往会将关系紧密的类组织到 包(package) 中。 按照UML的定义, 包是一组命名的建模元素集合。一个包可能包含其他包。
在UML中,包是一个 逻辑设计 概念。最终,包必须 实现 并 映射 为编程语言。 Java和C#语言提供了包 概念 到 实现 的直接映射。 通过类的名字空间和引入其他包的形式来支持实现包。
如果包A的一些成员在某种程度上引用了包B的某些成员(包A导入了包B的一些成员), 这隐含着双重含义:
本质上,两个 包之间的依赖性 来自于两个包中 类之间的依赖性 。
Figure 5: 包之间的循环依赖性
Figure 6: 消除包之间的循环依赖性
传统的 构件 也称为 模块 ,是软件体系结构的一部分。
在面向对象的软件工程环境中,面向对象技术已达到了类级复用,这样的复用粒度还太小。 构件 级复用则是比 类 级复用更高一级的复用。
为了能够支持复用,软件构件应具有以下特性:
在目前的很多系统中,构件被实现为更大粒度的单元,系统中的构件只能有一个实例。
例如,一个数据库服务器可以作为构件, 而它所管理的数据库(可以是一个,也可以是多个)并不是构件, 而是数据库“对象”实例。
软件构件 是一种 组装单元 ,它具有规范的 接口规格说明 和显式的 语境依赖 。 软件构件可以被 独立部署 ,并由第三方 任意组装 。
系统中某一 定型化的 、 可配置的 和 可替换的 部件 , 该 部件 封装了 实现 并暴露一系列 接口 。
上面的两个定义中都提到接口的概念,构件之间是通过接口相互连接的。 接口是可被客户访问的具体操作的集合,每个操作有规定的语义。
构件图 表示构件之间的 依赖关系 , 每个构件 实现(支持) 一些接口,并 使用 另一些接口。
Figure 7: 构件之间的依赖关系
在大型和复杂的软件系统中,首先根据需求的 功能模型(用例模型) ,
Figure 8: 系统结构的类图
面向对象的系统设计 主要关注 每个子系统提供服务的定义 , 即枚举所有的 操作 、 操作参数 和 行为 。
因此,当编写子系统接口的文档时,应 不涉及 子系统 实现 的细节, 其目的是 减少 子系统之间的 依赖性 。
子系统分层 的目的是建立系统的 层次结构 。
Figure 9: 封闭体系结构示例
Figure 10: 开放体系结构示例
Figure 11: 典型的面向对象设计模型
在软件系统中,提供服务的一端称为 服务器端 ,而将使用服务的一端称为 客户端 。
单向交互 比 双向交互 更容易理解,也更容易设计和修改, 因此,应该尽量使用 客户-供应商关系 。
混合使用 层次结构 和 块状结构 ,可以成功地由多个子系统组成一个完整的软件系统。
当混合使用层次结构和块状结构时, 同一层次可以由若干块组成 ,而 同一块也可以分为若干层 。
参与人数 | 0 |
---|---|
数据库层 | 0 |
业务逻辑层 | 0 |
用户界面层 | 0 |
面向对象的分析模型 包括有 用例图 、 类图 、 顺序图 和 包图 , 主要是对问题领域进行描述,基本上不考虑 技术实现 ,也不考虑 数据库层 和 用户界面层 。
用户界面(即人机交互界面) 是人机交互的主要方式, 用户界面的质量直接影响到用户对软件的使用, 对用户的 情绪 和 工作效率 也会产生重要影响, 也直接影响用户对软件产品的评价,从而影响软件产品的 竞争力 和 寿命 。
在设计阶段必须根据需求把 交互细节 加入到用户界面设计中, 包括人机交互所必需的 实际显示 和 输入 。
在某些情况下,界面设计师可以从每个界面 状态草图 开始, 如在 各种环境下 用户界面看起来是个什么样子; 接下来定义 对象 、 动作 和其他重要的设计信息。
无论应用的 领域 、 规模 和 复杂度 如何, 界面设计目标都应能在相应的Web应用系统中适用。
一个普通的类可以映射为 一个 表 或 多个 表 , 当分解为多个表时,可以采用 横切 和 竖切 的方法。
对象设计 以 问题域的对象设计 为核心,其结果是一个 详细的对象模型 。
经过多次反复的 分析 和 概要设计 之后,设计者通常会发现有些内容没有考虑到。 这些没有考虑到的内容,会在 对象设计 的过程中被发现。
在面向对象设计过程中, 设计模式 是开发者通过很长时间的实践而得到的重复出现问题的 模板化解决方案 。