设计模式

一、设计模式来源

设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。

二、设计模式六大原则

总原则——开闭原则(Open Closed principle)

一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭。

在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。

想要达到这样的效果,我们需要使用接口和抽象类等。

单一职责原则

Single Responsibility Principle

一个类应该只有一个发生变化的原因

不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,否则就应该把类拆分。

里氏替换原则

Liskov Substitution Principle

所有引用基类的地方必须能透明地使用其子类的对象

任何基类可以出现的地方,子类一定可以出现。里氏替换原则是继承复用的基石,只有当衍生类可以替换基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

里氏替换原则是对“开-闭”原则的补充。实现“开闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范。里氏替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。

依赖倒置原则

Dependence Inversion Principle

  1. 上层模块不应该依赖底层模块,它们都应该依赖于抽象
  2. 抽象不应该依赖于细节,细节应该依赖于抽象

面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。

接口隔离原则

Interface Segregation Principle

  1. 客户端不应该依赖它不需要的接口
  2. 类间的依赖关系应该建立在最小的接口上

每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

迪米特法则(最少知道原则)

Law of Demeter

只与你的直接朋友交谈,不跟“陌生人”说话

一个类对自己依赖的类知道的越少越好。无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。

合成复用原则

Composite Reuse Principle

尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的。

合成或聚合可以将已有对象纳入到新对象中,使之成为新对象的一部分,因此新对象可以调用已有对象的功能。

1
2
3
4
5
6
7
8
9
SOLID CD
S: single responsibility principle
O: open closed principle
L: liskov substitution principle
I: interface segregation principle
D: dependence inversion principle

C: composite reuse principle
D: law of Demeter

三、设计模式的三大类

创建型模式

Creational Pattern

关注如何创建对象,核心思想是要把对象的创建和使用相分离,这样使得两者能相对独立地变换。

包括:

  • 工厂方法:Factory Method
  • 抽象工厂:Abstract Factory
  • 建造者:Builder
  • 原型:Prototype
  • 单例:Singleton
1
创工原单建抽(创公园,但见愁)

结构型模式

Structural Pattern

关注对象的组成以及对象间的依赖关系,描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以通过简单积木的组合形成复杂的、功能更为强大的结构。

包括:

  • 适配器
  • 装饰着
  • 代理
  • 外观
  • 桥接
  • 组合
  • 享元
1
结享外组适代装桥(姐想外租,世代装桥)

行为型模式

Behavioral Pattern

关注对象的行为问题,是对在不同的对象之间划分责任和算法的抽象化;不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。

包括:

  • 策略模式
  • 模板方法
  • 观察者
  • 迭代器
  • 责任链
  • 命令模式
  • 备忘录
  • 状态模式
  • 访问者
  • 中介者
  • 解释器
1
行状责中模访解备观策命迭(形状折中模仿,戒备观测鸣笛)

四、C++常见设计模式

  1. 智能指针shared_ptr,unique_ptr,weak_ptr:代理模式
  2. STL中的queue:适配器模式
  3. STL中的iterator:迭代器模式
  4. 拷贝构造函数/拷贝复制运算符进行深拷贝:原型模式
  5. std::optional:空对象模式
  6. 虚函数实现运行时多态:策略模式
  7. std::string_view:享元模式

五、编码常用设计模式

以下内容参考 https://github.com/FengJungle/DesignPattern

简单工厂模式

创建型模式关注对象的创建过程,在软件开发中应用非常广泛。创建型模式描述如何将对象的创建和使用分离,让用户在使用对象过程中无须关心对象的创建细节,从而降低系统耦合度,并且让系统易于修改和扩展。

简单工厂模式是最简单的设计模式之一,其实它并不属于Gof的23中设计模式,但应用也十分频繁,同时也是其余创建模式的基础,因此有必要先学习简单工厂模式。

https://github.com/FengJungle/DesignPattern/blob/master/01.SimpleFactory/01.SimpleFactory.md

工厂模式

单例模式

Singleton Pattern,也称单件模式,使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

定义一个单例类:

  1. 私有化它的构造函数,以防止外界创建单例类的对象;
  2. 使用类的私有静态指针变量指向类的唯一实例;
  3. 使用一个公有的静态方法获取该实例。

实现方式:

  • 懒汉式,线程不安全
  • 懒汉式加锁
  • 懒汉式双检锁(DCL,double-checked-locking)
  • 饿汉式
  • 静态内部类
  • 枚举

参考:

适配器模式

外观模式

代理模式

包装模式(装饰器模式)

桥接模式

模板方法模式

策略模式

观察者模式

责任链模式