09~12-详细设计
详细设计的输入
需求规格说明:分析类图、系统顺序图
体系结构设计:接口
详细设计的输出:设计类图
职责分配
功能职责:方法
数据职责:属性
协作职责:与其他类的关系
从小到大,将对象的小职责聚合成大职责
从大到小,将大职责分配给每个小对象
GRASP 设计原则
低耦合 Low-Coupling:减少模块之间的依赖关系
高内聚 High-Cohesion:模块内部的元素之间的关系越紧密越好
信息专家:拆分职责,职责分配给拥有所需信息的类
创建者
控制者
创建者
以下优先级从高到低排列
组合关系
整体对象的创建定义和操作方法
整体对象的创建
例如,销售的业务逻辑对象由销售项对象创建
被某个对象记录和管理(单向关联)
关联对象的方法
业务方法的执行中对象的生命周期与此对象同步
连接池创建连接池对象
创建所需的数据被某个对象所持有
持有数据对象的方法
业务方法的执行中
也可由其他对象创建,由持有数据的对象初始化
聚合关系
整体对象的业务方法
业务方法的执行中
某个对象有多个关联时,优先选择聚合关联的整体对象,若有多个根据高内聚、低耦合的原则确定
其他
-
-
根据高内聚、低耦合原则确认
控制者
目的:分配处理系统事件(外部事件)的职责
解决方法:专门建立
Controller类,作为中介分配事件处理的职责推荐的控制器候选类别(具体选择基于高内聚、低耦合原则)
整个系统:
SystemController某个业务/系统总体组织的类:
OrderController在业务逻辑中“有行为”的角色:
Cashier对于每个用例人为设计的控制器类:
LoginHandler
集中式
所有事件都在一个主控模块中处理(调用主控模块的方法)
设计简单,易于实现
复杂度高,耦合度高,难以维护
委托式
事件在主控模块中分发到其他模块处理(调用其他模块,由其他模块调用内部方法)
分散式
事件在数据和职责较少的模块间传输,完成处理
内聚度低带来高耦合,控制流复杂,模块散乱
画图
类图:详见 UML 速查
顺序图:和需求中的顺序图类似,需要将自然语言描述的方法转换为 实际的方法名称
耦合
耦合:模块间关系的复杂程度
以下分类从高到低排序
内容耦合
模块直接访问另一模块的内部内容
直接访问内部变量、函数、GOTO跳入另一模块内部
公共耦合
模块通过公共变量共享数据
全局变量
重复耦合
模块间有重复逻辑的代码
代码复制
控制耦合
模块通过控制信息影响另一个模块的行为
传递标志位、状态等
印记耦合
共享数据结构,但是只使用了其中一部分
传递一个对象,但只使用了其中的一个属性
数据耦合
模块通过参数传递数据
函数参数
内聚
内聚:衡量模块内部元素之间的相关性
逻辑内聚和控制耦合常相关
以下分类从低到高排序
偶然内聚
模块执行完全无关的操作
修车、烤面包、遛狗
逻辑内聚
模块内操作相关(在逻辑、功能层面一致),但调用由其他模块决定
开车去、坐火车去
时间内聚
模块内操作和时间相关,本身不存在逻辑关系
起床、刷牙、洗脸、吃早餐
过程内聚
模块内的操作按特定顺序执行,存在逻辑关系
守门员传球给后卫,后卫传球给中场球员 ……
通信内聚
模块执行的操作在相同数据上进行
查书的作者、名字、出版商
功能内聚
模块内的操作共同完成单一功能
计算平方根
信息内聚
模块基于相同的数据结构,执行不同操作,各操作入口点、代码独立
栈
面向对象的模块化
降低隐式耦合
全局变量有害
简洁
避免代码重复
降低访问耦合
访问耦合:链式调用,
c = a().b()面向接口编程:主动设计需求接口
迪米特法则:避免链式调用,只能出现一次
.若
O有方法m(),则O只能调用:O自身、O的成员变量、m的参数、m中局部变量的方法
接口分离原则 ISP:接口应尽量独立、精简,避免实现者实现不必要的接口
降低继承耦合
继承耦合:子类覆盖父类已有的代码
修改规格
子类修改父类的接口声明
修改实现
子类修改父类的实现,接口声明不变
精化规格
子类基于更严格的规则,修改父类的接口声明
精化实现
子类基于更严格的规则,修改父类的实现,接口声明不变
拓展
子类不对父类作更改,只增加新的方法、成员变量
无
两个类之间无继承关系
Liskov 替换规则 LSP:所有子类必须可以替换父类
使用组合代替继承:可以在
Stack中包含一个List,而不是继承自List
提高内聚
单一职责原则 SRP:一个类只有一个引起变化的原因,每个类只负责单一功能
信息隐藏
基本思想:模块隐藏重要设计决策的内部实现,只暴露必要的接口
两种信息隐藏决策:按职责/算法分解,前者更好
设计原则
封装
封装数据和行为:部分属性无需暴露 Getter 和 Setter,不要暴露存储数据和推导数据
calculateAge封装内部结构:传递迭代器对象而非原来对象
封装对象的引用:Getter 方法返回一个新的引用
封装类型信息:使用父类的接口隐藏子类的类型信息
封装可能存在的变更
权限最小化原则
开闭原则 OCP:对扩展开放,对修改关闭,添加新的代码而不需要修改原来的代码就能实现变更(善用多态)
依赖倒置原则 DIP:高层模块不应该依赖低层模块,二者都应该依赖抽象(接口或抽象类),抽象不应该依赖细节,细节应该依赖抽象
解决方案:为具体类建立接口
最后更新于