设计模式学习笔记(一):https://www.jianshu.com/p/15e5bbe078f5
5. 单例模式
确保只有一个对象被实例化(如线程池、缓存、注册表……)
其他实现方式:静态变量、全局变量……
具体实现
构造函数是私有的,但有公开的“请求函数”,请求函数伪代码:
if(unique == NULL) // 如果没有被构造出来
return unique = new Unique(); // 构造对象并返回
return unique; // 否则返回对象
多线程的改进方法:
方案一、加锁
if(unique == NULL) // 如果没有被构造出来
{
mutex.lock(); // 防止所线程同时访问构造对象,因此需要加锁
return unique = new Unique(); // 构造对象并返回
mutex.unlock();
}
return unique; // 否则返回对象
方案二、Unique类中创建private static类型的unique对象,每次请求函数都返回这个对象。
以前我写的程序会用到“global”类,这就是这种方法的一个不正式的变体。
注意
单例类不能继承。
6. 命令模式
命令模式的目的是具体操作和具体操作者之间的解耦;
优缺点(《Python 设计模式》)
命令模式的优点:
- 将调用操作的类和知道如何执行该操作的对象解耦;
- 提供队列系统后,可以创建一系列命令;
- 添加新命令更容易,并且无需更改现有的代码;
- 还可以使用命令模式来定义回滚系统,例如,在向导实例中,我们可以便也一个回滚方法。
命令模式的缺点: - 为了实现目标,需要大量的类和对象进行协作。应用程序开发人员为了正确开发这些类,需要倍加小心;
- 每个单独的命令都是一个ConcreteCommand类,从而增加了需要实现和维护的类的数量。
大概执行
不同对象执行的具体操作都继承于一个抽象类,因此调用操作的函数只需要调用抽象类的核心操作即可。
命令模式
例子(《Head First 设计模式》)
遥控器 ,多个按钮和对应的槽。按钮按下后执行的指令是执行传入的command类的具体子类的excute操作。
7. 适配器模式
顾名思义,适配器模式就是把一个接口转化为另一个接口。改变一个接口,使得它看起来更像另一个接口,以便实现不同的接口。
对象适配器的大概实现
在适配器类中新建一个源对象,适配器类的构造入参就是源对象类……
适配器示意图
对象适配器UML图
例子(《Head First 设计模式》)
如果有个东西很像鸭子,那么它可能是只装了鸭子适配器的火鸡7.5 外观模式(门面模式)
简化接口。
PS:知识最少原则
8. 模板方法模式
核心:封装算法
模板方法定义了一个算法的步骤,并且允许子类为一个或者多个步骤提供实现。
适用场景(《Python 设计模式》):
- 当多个算啊发或者类实现类似或者相同逻辑的时候;
- 当子类中实现算法有助于减少重复代码的时候;
- 可以让子类利用覆盖实现行为来顶一个多个算法的时候。
优缺点
优点:
- 没有代码重复。由于模板方法使用继承而不是合成,因此能够对代码进行重用,所以只有为数不多的代码需要重写。
- 灵活性允许子类决定如何实现算法中的步骤。
缺点: - 调试和理解模板方法模式中的流程序列有时会令人困惑。
-
模板框架维护可能是一个会很痛苦,因为任何层次(底层或高层)的变更都可能对显示造成干扰。
模板方法模式UML图
例子(《head first 设计模式》)
咖啡因饮料
例子(《Python设计模式》)
旅行社提供旅行规划
钩子函数
钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现,钩子的存在,可以让子类 有能力对算法的不同点进行挂钩。但要不要挂钩,由子类自己决定。
钩子有几种用法:
- 可以实现算法中可选的部分;
- 让子类有机会对模板方法中某些即将发生的(或刚刚发生的)步骤作出反应。
钩子函数例子
钩子函数例子
PS:好莱坞原则——高层组件调用低层组件,低层组件不得调用高层组件。
网友评论