软件设计模式期末复习
0. OMT
0.1 实例化(创建)
如图表示CreationTool
创建了LineShape
类型的对象
0.2 继承(继承)
上面表示LineShape
这个类是Shape
这个类的子类
0.3 组合
class Drawing
{
Shape ShapeVar;
}
0.4 聚合
class LineShape
{
Color* ColorVar;
}
0.5 多个
OMT还定义了一种实心圆点,表示“多于一个”:
上图表示Drawing
类有多个Shape
类型的成员变量
0.6 伪代码注解
1.六选三类图(
1.1 Iterator迭代器
1.2 Mediator中介者
1.3 Memento备忘录
1.4 Observer观察者
1.5 State状态
1.6 Strategy策略
2.简答题
2.1模式的意图
2.1.1 原型Prototype
用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
2.1.2 组成Composite
将对象组合成树形结构以表示“部分-整体”的层次结构。
Composite使得客户对单个对象和复合对象的使用具有一致性。
2.1.3 策略Strategy
定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。
本模式使得算法的变化可独立于使用它的客户。
2.1.4 外观Facade
为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
2.1.5 工厂方法Factory-Method
定义一个用于创建对象的接口。Factory Method使一个类的实例化延迟到其子类。
2.2 OO的设计原则(七选二)
设计原则名称 | 设计原则简介 | 重要性 |
---|---|---|
单一职责原则(Single Responsibility Principle, SRP) | 类的职责要单一,不能将太多的职责放在一个类中 | ★★★★☆ |
开闭原则(Open-Closed Principle, OCP) | 软件实体对扩展是开放的,但对修改是关闭的,即在不修改一个软件实体的基础上去扩展其功能 | ★★★★★ |
里氏代换原则(Liskov Substitution Principle, LSP) | 在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类对象 | ★★★★☆ |
依赖倒转原则(Dependency Inversion Principle, DIP) | 要针对抽象层编程,而不要针对具体类编程 | ★★★★★ |
接口隔离原则(Interface Segregation Principle, ISP) | 使用多个专门的接口来取代一个统一的接口 | ★★☆☆☆ |
合成复用原则(Composite Reuse Principle, CRP) | 在系统中应该尽量多使用组合和聚合关联关系,尽量少使用甚至不使用继承关系 | ★★★★☆ |
迪米特法则(Law of Demeter, LoD) | 一个软件实体对其他实体的引用越少越好,或者说如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互 | ★★★☆☆ |
2.3 三选一
2.3.1 白箱复用和黑箱复用对比
优缺点:
继承复用(“白箱”复用 ):
- 实现简单,易于扩展。
- 破坏系统的封装性;
- 从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;
- 只能在有限的环境中使用。
组合/聚合复用(“黑箱”复用 ):
- 耦合度相对较低,选择性地调用成员对象的操作;
- 可以在运行时动态进行。
对比:
组合/聚合可以使系统更加灵活,类与类之间的耦合度降低,一个类的变化对其他类造成的影响相对较少,因此一般首选使用组合/聚合来实现复用;其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。
2.3.2 观察者模式谁启动的更新
目标和它的观察者依赖于通知机制来保持一致。但到底哪一个对象调用N o t i f y来触发更新? 此时有两个选择:
- 由目标对象的状态设定操作在改变目标对象的状态后自动调用 N o t i f y。这种方法的优点是客户不需要记住要在目标对象上调用 N o t i f y,缺点是多个连续的操作会产生多次连续的更新, 可能效率较低。
- 让客户负责在适当的时候调用 N o t i f y。这样做的优点是客户可以在一系列的状态改变完成后再一次性地触发更新 ,避免了不必要的中间更新。缺点是给客户增加了触发更新的责任。由于客户可能会忘记调用 N o t i f y,这种方式较易出错。
2.3.1 Facade外观模式和Mediator模式的对比
各自的意图:
- Facade:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
- Mediator:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
Facade与中介者的不同之处在于它是对一个对象子系统进行抽象,从而提供了一个更为方便的接口。它的协议是单向的,即 Facade对象对这个子系统类提出请求,但反之则不行。相反,Mediator提供了各Colleague对象不支持或不能支持的协作行为,而且协议是多向的。
3.设计题
3.1 第五次作业Command类图以及简单说明
public static void main(String[] args) {
UserInvoker userInvoker = new UserInvoker();
userInvoker.compute(CalculatorReceiver.Operation.ADD, 10, 20);
userInvoker.compute(CalculatorReceiver.Operation.SUB, -10, 50);
userInvoker.compute(CalculatorReceiver.Operation.MUL, 20, 30);
userInvoker.undo(); // 撤销20 * 30的操作
userInvoker.undo(); // 撤销 -10 - 50的操作
userInvoker.redo();// 重做 -10 s- 50操作
userInvoker.redo();// 重做 20 * 30操作
userInvoker.redo();// 没有需要redo的操作
}
3.2 发布订阅模式实例
4.综合设计题目
两个设计模式以上
4.1 常用设计模式应用场景
4.2 系统设计设计模式考虑方向
- Facade 模式描述了怎样用对象表示完整的子系统。
- Flyweight 模式描述了如何支持大量的最小粒度的对象。
- 其他一些设计模式描述了将一个对象分解成许多小对象的特定方法。
- Abstract Factory 和 Builder 模式产生那些专门负责生成其他对象的对象。
- Visitor 和 Command 生成的对象专门负责实现对其他对象或对象组的请求。
4.3 系统设计实例样例
4.3.1 单例模式
功能说明:注册界面使用了单例模式,点击注册按钮时,无论如何,都只能打开一个注册界面。如果不使用单例模式对注册窗口对象进行唯一化,则将弹出多个窗口且这些窗口显示的内容完全一致,浪费内存资源。
4.3.2 适配器模式 或者 策略模式
功能说明:账号密码用到了适配器模式,将密码加密后再存储在数据库中。此将目标类和加密适配器类进行解耦,增加了类的透明性和复用性,同时系统的灵活性和扩展性都非常好,更换加密适配器或增加新的加密适配器都非常方便,符合“开闭原则”, 同时采用策略模式将用于加密的算法也可以随着系统安全性需求的提高更换安全性更高的加密算法。
4.3.3 外观模式
功能说明:在JDBC数据库操作中用到了外观模式。在进行数据库操作的时候,首先需要创建连接Connection对象,然后通过Connection对象创建语句Statement对象或其子类的对象,如果是数据查询语句,通过Statement对象可以获取结果集ResultSet对象。在大部分数据操作代码中都多次定义了这三个对象,本人在此部分使用外观模式简化了JDBC操作代码。
4.3.4 备忘录模式
功能说明:用户信息管理模块用到了备忘录模式,在用户信息管理模块中,用户可以修改自己的各项信息,在进行了错误操作之后,用户可以进行撤销,恢复到之前的状态,使得系统更加的人性化。
4.3.5 策略模式
不同形式的登录, 密码 手机号短信验证 二维码登录