目录
什么是设计模式
设计模式是指在软件开发过程中,经过验证的,用于解决在特定环境下,重复出现的,特定问题的解决方案。
创建型设计模式
模板方法
定义:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
要点:
- 最常用的设计模式,子类可以复写父类的子流程,使父类的骨架流程丰富
- 反向控制流程的典型应用
- 父类protected保护子类需要复写的子流程,这样子类的子流程只能父类来调用
本质:
- 通过固定算法骨架来约束子类的行为
结构图:
观察者模式
定义:
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(subject)的状态发生改变时,所有依赖与它的对象都得到通知并自动更新。
要点:
- 观察者模式使得我们可以独立的改变目标与观察者,从而使二者之间的关系松耦合
- 观察者自己决定是否订阅通知,目标对象并不关注谁订阅了
- 观察者不要依赖通知顺序,目标对象也不知道通知顺序
- 常用在基于事件的ui框架中,也是MVC的组成部分
- 常用在分布式系统中,actor框架中
本质:
- 触发联动
结构图:
策略模式
定义:
定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。该模式使得算法可独立于使用它的客户程序而变化
要点:
- 策略模式提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换
- 策略模式消除了条件判断语句,也就是在解耦合
本质:
- 分离算法,选择实现
结构图:
结构型设计模式
单例模式
定义:
保证一个类仅有一个实例,并提供一个该实例的全局访问点。
代码一
class Singleton {
public:
static Singleton * GetInstance() {
if (_instance == nullptr)
{
_instance = new Singleton();
atexit(Destructor); //main函数退出时执行资源清理
}
return _instance;
}
private:
static void Destructor() {
if (nullptr != _instance)
{
delete _instance;
_instance = nullptr;
}
}
Singleton();//构造
~Singleton() {}
Singleton(const Singleton &cpy); //拷⻉构造
Singleton& operator=(const Singleton& other) {}//赋值
static Singleton * _instance; //静态指针
};
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
// 还可以使⽤ 内部类,智能指针来解决; 此时还有线程安全问题
代码二
// c++11 magic static 特性:如果当变量在初始化的时候,并发同时进⼊声明语句,并发线程将会阻塞等待初始化结束。
// c++ effective
class Singleton
{
public:
static Singleton& GetInstance() {
static Singleton instance; //创建全局静态变量,整个程序只会有一份数据且结束后自动释放
return instance;
}
private:
Singleton(){}
~Singleton() {}
Singleton(const Singleton&) {}
Singleton& operator=(const Singleton&) {}
};
// 继承 Singleton
// g++ Singleton.cpp -o singleton -std=c++11
/*该版本具备所有优点:
1. 利⽤静态局部变量特性,延迟加载;
2. 利⽤静态局部变量特性,系统⾃动回收内存,⾃动调⽤析构函数;
3. 静态局部变量初始化时,没有 new 操作带来的cpu指令reorder操作(内存屏障);
4. c++11 静态局部变量初始化时,具备线程安全;
*/
工厂方法
定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。
要点:
解决创建过程中比较复杂,希望对外隐藏这些细节的场景
- 比如连接池、线程池
- 隐藏对象真实类型
- 对象创建会有很多参数来决定如何创建
- 创建对象有复杂的依赖关系
本质:
- 延迟到子类
结构图:
抽象工厂
定义:
提供一个接口,让该接口负责创建一系列“相关或者互相依赖的对象”,无需指定它们具体的类。
结构图:
责任链
定义:
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
要点:
- 要解耦请求方和处理方,请求方不知道请求是如何处理的,处理方的组成是由相互独立的子处理构成,子处理流程通过链表的方式连接,子处理请求可以按任意顺序组合
- 责任链请求强调请求最终由一个处理流程处理;通过了各个子处理条件判断
- 责任链扩展就是功能链,功能链强调的是,一个请求依次经由功能链中的子处理流程
- 将职责以及职责顺序运行进行抽象,那么职责变化可以任意扩展,同时职责顺序也可以任意扩展
本质:
- 分离职责,动态组合
结构图:
装饰器
定义:
动态的给一个对象增加一些额外的职责。就增加功能而言,装饰器模式比生产子类更为灵活。
要点:
- 通过采用组合而非继承的方法,装饰器模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”
- 不是解决“多子类衍生问题”的问题,而是解决“父类在多个方向上的扩展功能”的问题
- 装饰器模式把一系列复杂的功能分散到每个装饰器当中,一般一个装饰器只实现一个功能,实现复用装饰器的功能
本质:
- 动态组合
结构图: