摘要
本文是 2024Fall-高级软件设计 的期末复习提纲,根据复习课录音整理,以供复习参考。
课程详细内容可参考 分类: 2023Spring-软件系统设计 | EagleBear2002 的博客 中的“软件详细设计”部分,这部分内容的授课教师和授课内容与本课程完全相同。
这份复习资料内容更加全面:南京大学软件学院-2023-高级软件设计(研究生)期末复习参考 - 知乎。
考试为英文题目,12 道简答题,1 道场景设计题。
设计原则
对于面向对象的软件系统设计来说,在支持可维护性的同时,需要提高系统的可复用性。
软件的复用可以提高软件的开发效率,提高软件质量,节约开发成本,恰当的复用还可以改善系统的可维护性。
- 开闭原则(可变性封装原则):要求一个软件实体应当对扩展开放,对修改关闭,即在不修改源代码的基础上扩展一个系统的行为。
- 迪米特法则:要求一个软件实体应当尽可能少的与其他实体发生相互作用。
- 单一职责原则:要求在软件系统中,一个类只负责一个功能领域中的相应职责。
- 里氏代换原则:可以通俗表述为在软件中如果能够使用基类对象,那么一定能够使用其子类对象。
- 依赖倒置原则:要求抽象不应该依赖于细节,细节应该依赖于抽象;要针对接口编程,不要针对实现编程。
- 接口隔离原则:要求客户端不应该依赖那些它不需要的接口,即将一些大的接口细化成一些小的接口供客户端使用。
- 合成复用原则:要求复用时尽量使用对象组合,而不使用继承。
设计原则之间的关系
- 目标:开闭原则
- 指导:迪米特法则(最小知识原则)
- 基础设计层面:单一职责原则、可变性封装原则
- 代码实现层面:依赖倒置原则、合成复用原则、里氏代换原则、接口隔离原则
设计模式
- 根据其目的(模式是用来做什么的)可分为创建型(Creational),结构型(Structural)和行为型(Behavioral)三种:
- 创建型模式主要用于创建对象。
- 结构型模式主要用于处理类或对象的组合。
- 行为型模式主要用于描述对类或对象怎样交互和怎样分配职责。
- 根据范围,即模式主要是用于处理类之间关系还是处理对象之间的关系,可分为类模式和对象模式两种:
- 类模式处理类和子类之间的关系,这些关系通过继承建立,在编译时刻就被确定下来,是属于静态的。
- 对象模式处理对象间的关系,这些关系在运行时刻变化,更具动态性。
范围/目的 | 创建型模式 | 结构型模式 | 行为型模式 |
---|---|---|---|
常用原则 | 里氏代换原则、可变性封装原则、合成复用原则 | 单一职责原则、依赖倒置原则、接口隔离原则 | |
类模式 | 工厂方法模式 | (类)适配器模式 | 模板方法模式 |
对象模式 | 抽象工厂模式、单例模式 | (对象)适配器模式、组合模式、装饰模式、外观模式、代理模式 | 命令模式、迭代器模式、观察者模式、状态模式、策略模式 |
具体设计模式的优点、缺点、应用场景,请参考 分类: 2023Spring-软件系统设计 | EagleBear2002 的博客。
设计模式和设计原则
所有的设计模式目标都是实现开闭原则,基本思想是使用迪米特法则。表中只展示具体实现使用的最主要的设计原则。
模式一般都会有的缺点:
- 增加设计的复杂度和增加类的个数(增加辅助类)
- 增加隔阂、方法调用,降低软件运行的效率,但是已经不是目前主要的问题了
模式名称 | 相关的设计原则 | 示例 | 缺点 |
---|---|---|---|
策略模式 | 可变性封装原则、依赖倒置原则 | 不同叫声的鸭子 | 客户端需要了解所有策略类的作用,增加使用复杂性 |
状态模式 | 可变性封装原则、依赖倒置原则 | 论坛用户等级 | 状态类数量增加,导致系统复杂度上升 |
观察者模式 | 单一职责原则、依赖倒置原则 | 天气预报推送 | 可能引起链式反应,增加系统复杂度 |
单例模式 | / | 可能导致过多依赖,全局状态增加系统耦合度 | |
装饰模式 | 里氏代换原则、可变性封装原则、合成复用原则 | 变形金刚 | 可能生成大量小对象,增加系统复杂性 |
工厂方法模式 | 依赖倒置原则、可变性封装原则 | 日志记录器 | 增加类的数量,系统复杂度增加 |
抽象工厂模式 | 依赖倒置原则、可变性封装原则 | 电器工厂 | 新增产品族时需要修改工厂接口,违反开闭原则 |
适配器模式 | 里氏代换原则、合成复用原则 | 仿生机器人 | 可能导致系统过于复杂,引入不必要的类 |
外观模式 | 迪米特法则、接口隔离原则(存疑) | 电源总开关 | 不能很好地限制客户端直接访问子系统 |
模板方法模式 | 单一职责原则、开闭原则 | 银行业务办理流程 | 子类实现复杂,导致系统可读性降低 |
命令模式 | 依赖倒置原则、单一职责原则 | 电视机遥控器 | 增加类的数量,系统复杂度增加 |
迭代器模式 | 单一职责原则、开闭原则 | C++ 容器 set |
增加了类的数量,可能导致系统复杂性增加 |
组合模式 | 里氏代换原则 | 文件系统 | 复杂性较高,调试和维护难度较大 |
代理模式 | 迪米特法则、合成复用原则、依赖倒置原则(存疑) | 论坛权限控制代理 | 增加类的数量,系统复杂度增加 |
策略模式 vs. 状态模式
两者的类结构完全相同。
- 状态切换是自动的,由状态类或上下文类决定。
- 策略切换由客户端决定,且切换通常是明确的。