面对对象设计
- 1、面对对象的架构设计
- 1.1 第一步:构造系统的物理模型
- 1.2 第二步:设计子系统
- 划分各个子系统的方式
- 定义子系统之间的关系
- 定义子系统的接口
- 1.3 第三步:非功能需求设计
- 2、面对对象的用例设计与类设计
- 2.1 类
- 2.2 类间关系
- 2.3 细化用例
- 第一步:定义类的属性
- 第二步:定义类的操作
- 第三步:定义类之间的关系
1、面对对象的架构设计
架构设计的目的是要勾画出系统的总体结构,这项工作由经验丰富的架构设计师主持完成。
输入:用例模型、分析模型。
输出:物理结构、子系统及其接口、概要的设计类。
1.1 第一步:构造系统的物理模型
- 首先用UML(统一建模语言)的配置图(部署图)描述系统的物理架构;
- 将需求分析阶段捕获系统功能分配到这些物理节点上;
- 配置图上可以显示计算节点的拓扑结构、硬件设备配置、通信路径、各个节点上运行的系统软件配置、应用软件配置;
一个图书馆信息管理系统的物理模型如后图所示:
1.2 第二步:设计子系统
- 对于一个复杂的软件系统而言,将其分解成若干个子系统,子系统内还可以继续划分子系统或包,这种自顶而下、逐步细化的组织结构非常符合人类分析问题的思路。
- 每个子系统与其他子系统之间应该定义接口,在接口上说明交互信息,注意这时还不要描述子系统的内部实现。
- 可用UML组件图表示。
划分各个子系统的方式
- 按照功能划分,将相似的功能组织在一个子系统中;
- 按照系统的物理布局划分,将在同一个物理区域内的软件组织为一个子系统:·
- 按照软件层次划分子系统,软件层次通常可划分为用户界面层、专用软件层、通用软件层、中间层和数据层。
定义子系统之间的关系
划分子系统后,要确定子系统之间的关系,子系统之间的关系:
1. 请求-服务”关系,“请求”子系统调用“服务”子系统。“服务”子系统完成一些服务井且将结果返回给“请求”子系统。
2. 平等关系,每个子系统都可以调用其它子系统,
3. 如果子系统的内容相互有关联,就应该定义它们之间的依赖关系。在设计时,相关的子系统之阎应该定义接口,依赖关系应该指向接口而不要指向子系统的内容。
如果两个子系统之间的关系过于密切,则说明一个子系统的变化会导致另一个子系统变化,这种子系统理解和维护都会比较困难,
解决子系统之间关系过于密切的办法基本上有两个:
1. 重新划分子系统,这种方法比较简单,将子系统的粒度减少,或者重新规划子系统的内容,将相豆依赖的元素划归到司一个子系统之中;
2. 定义子系统的接口,将依赖关系定文到接口上
定义子系统的接口
每个子系统的接口上定义了若干提作,体现了子系统的功能,而功能的具体实现方法应该是隐藏的,其他子系统只能通过接口间接地享受这个子系统提供的服务。不能直接作它。
1.3 第三步:非功能需求设计
分析阶段定义了整个系统的非功能需求,在设计阶段要研究这些需求,设计出可行的方案。
非功能需求包括:系统的安全性、错误监测和故障恢复、可移植性和通用性等等。
具有共性的非功能需求一般设计在中间层和通用空用层,目的是充分利用已有构件,减少重新开发的工作量。
2、面对对象的用例设计与类设计
面对对象设计活动之二:进一步细化用例。
- 根据分析阶段产生的高层类图和交互图,由用例设计师研究已有的类,将它们分配到相应的用例中。
- 检查每个用例功能,依靠当前的类能否实现,同时检查每个用例的特殊需求是否有合活的类来实现。
- 细化每个用例的类图,描述实现用例的类及其类之间的相互关系,其中的通用类和关键类可用粗线框区分,这些类将作为项目经理检查项目时的重点。
2.1 类
类是包含信息和影响信息行为的逻辑元素。类的符号是由三个格子的长方形组成,有时下面两个格子可以省略。
最顶部的格子包含类的名字,类的命名应尽量用应用领域中的术语,有明确的含义,以利于开发人员与用户的理解和交流。中间的格子说明类的属性,最下面的格子是类的操作行为。
2.2 类间关系
关联、聚合、组合、依赖、泛化。
- 分析类图:在需求分析阶段使用
- 如何找边界类?
参与者与用例之间应当建立边界类。
用例与用例之间如果有交互,应当为其建立边界类。
如果用例与系统边界之外的非人对象有交互,应当为其建立边界类。
在相关联的业务对象有明显的独立性要求,即它们可能在各自的领域内发展和变化,但又希望互不影响时,也应当为它们建立边界类。 - 如何找控制类?
控制类来源于对用例场最中动词的分析和定义。
控制类主要起到协调对象的作用,例如从边界类通过控制类访问实体类,或者实体类通过控制类访问另一个实体类。
如果用例场景中的行为在执行步骤、执行要求或者执行结果上具有类似的特征,应当合并或独取超类。
2.3 细化用例
第一步:定义类的属性
用所选择的编程语言定义每个类的属性。类的属性反映类的特性,通常属性是被封装在类的内部,不允许外部对象访问。
注意点:
1. 分析阶段和概要设计阶段定义的一个类属性在详细设计时可能要被分解为多个,减小属性的表示粒度有利于实现和重用,但是一个类的属性如果太多,则应该检查一下,看能否分离出一个新的类。
2. 如果一个类因为其属性的原因变得复杂而难于理解,那么就将一些属性分离出来形成一个新的类。
3. 通常不同的编程语言提供的数据类型有很大差别,确定类的属性时要用编程语言来约束可用的属性类型,定义属性类型时尽可能使用已有的类型,太多的自定义类型会降低系统的可维护性和可理解性等性能指标。
4. 类的属性结构要坚持简单的原则,尽可能不使用复杂的数据结构。
第二步:定义类的操作
由构件工程师为每个类的方法设计必须实现的操作,并用自然语言或伪代码描述操作的实现算法。一个类可能被应用在多个用例中,由于它在不同用例中担当的角色不同,所以设计时要求详细周到.
注意事项:
1. 分析类的每个职责的具体含义,从中找出类应该具备的摄作。
2. 阅读类的非功能需求说明,添加一些必须的操作。
3. 确定类的接口应该提供的摄作。这关系到设计的质量,特别是系统的稳定性,所以确定类接口操作要特别小心。
4. 逐个检查类在每个用例实现中是否合适,补充一些必须的操作。
5. 设计时不仅要考虑到系统正常运行的情况,还要考虑一些特殊情况,如中断/错误处理等。
第三步:定义类之间的关系
设置基数:一个类的实例与另一个类的实例之间的联系。在图书馆信息管理系统中,“图书”类和“读者”类关联,如果需求说明中有“一位读者可借图书的数量为0至10本”,那么它们之间的基数为1:0…10。
使用关联类:可以放置与关联相关的属性。例如“图书”类和“读者”类,如果要反映读者的借书情况该如何处理呢?可以创建一个关联类,这个类中的属性是“借书日期”。