设计模式
设计模式
一、设计模式来源
设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。
二、设计模式六大原则
总原则——开闭原则(Open Closed principle)
一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭。
在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。
想要达到这样的效果,我们需要使用接口和抽象类等。
单一职责原则
Single Responsibility Principle
一个类应该只有一个发生变化的原因
不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,否则就应该把类拆分。
里氏替换原则
Liskov Substitution Principle
所有引用基类的地方必须能透明地使用其子类的对象
任何基类可以出现的地方,子类一定可以出现。里氏替换原则是继承复用的基石,只有当衍生类可以替换基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
里氏替换原则是对“开-闭”原则的补充。实现“开闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范。里氏替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。
依赖倒置原则
Dependence Inversion Principle
- 上层模块不应该依赖底层模块,它们都应该依赖于抽象
- 抽象不应该依赖于细节,细节应该依赖于抽象
面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
接口隔离原则
Interface Segregation Principle
- 客户端不应该依赖它不需要的接口
- 类间的依赖关系应该建立在最小的接口上
每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。
迪米特法则(最少知道原则)
Law of Demeter
只与你的直接朋友交谈,不跟“陌生人”说话
一个类对自己依赖的类知道的越少越好。无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。
合成复用原则
Composite Reuse Principle
尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的。
合成或聚合可以将已有对象纳入到新对象中,使之成为新对象的一部分,因此新对象可以调用已有对象的功能。
1 | SOLID CD |
三、设计模式的三大类
创建型模式
Creational Pattern
关注如何创建对象,核心思想是要把对象的创建和使用相分离,这样使得两者能相对独立地变换。
包括:
- 工厂方法:Factory Method
- 抽象工厂:Abstract Factory
- 建造者:Builder
- 原型:Prototype
- 单例:Singleton
1 | 创工原单建抽(创公园,但见愁) |
结构型模式
Structural Pattern
关注对象的组成以及对象间的依赖关系,描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以通过简单积木的组合形成复杂的、功能更为强大的结构。
包括:
- 适配器
- 装饰着
- 代理
- 外观
- 桥接
- 组合
- 享元
1 | 结享外组适代装桥(姐想外租,世代装桥) |
行为型模式
Behavioral Pattern
关注对象的行为问题,是对在不同的对象之间划分责任和算法的抽象化;不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。
包括:
- 策略模式
- 模板方法
- 观察者
- 迭代器
- 责任链
- 命令模式
- 备忘录
- 状态模式
- 访问者
- 中介者
- 解释器
1 | 行状责中模访解备观策命迭(形状折中模仿,戒备观测鸣笛) |
四、C++常见设计模式
- 智能指针shared_ptr,unique_ptr,weak_ptr:代理模式
- STL中的queue:适配器模式
- STL中的iterator:迭代器模式
- 拷贝构造函数/拷贝复制运算符进行深拷贝:原型模式
- std::optional:空对象模式
- 虚函数实现运行时多态:策略模式
- std::string_view:享元模式
五、编码常用设计模式
以下内容参考 https://github.com/FengJungle/DesignPattern
简单工厂模式
创建型模式关注对象的创建过程,在软件开发中应用非常广泛。创建型模式描述如何将对象的创建和使用分离,让用户在使用对象过程中无须关心对象的创建细节,从而降低系统耦合度,并且让系统易于修改和扩展。
简单工厂模式是最简单的设计模式之一,其实它并不属于Gof的23中设计模式,但应用也十分频繁,同时也是其余创建模式的基础,因此有必要先学习简单工厂模式。
https://github.com/FengJungle/DesignPattern/blob/master/01.SimpleFactory/01.SimpleFactory.md
工厂模式
单例模式
Singleton Pattern,也称单件模式,使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
定义一个单例类:
- 私有化它的构造函数,以防止外界创建单例类的对象;
- 使用类的私有静态指针变量指向类的唯一实例;
- 使用一个公有的静态方法获取该实例。
实现方式:
- 懒汉式,线程不安全
- 懒汉式加锁
- 懒汉式双检锁(DCL,double-checked-locking)
- 饿汉式
- 静态内部类
- 枚举
参考:
- https://m.runoob.com/design-pattern/singleton-pattern.html
- https://zhuanlan.zhihu.com/p/37469260
- Qt 使用 Http 下载