本文创建于 2024-11-29;修改于 2024-11-29

一、设计原则

1. 依赖倒置

实现依赖抽象(接口),用户也依赖抽象。

高层模块不应该依赖低层模块,两者都应该依赖抽象;

抽象不应该依赖具体实现,具体实现应该依赖于抽象;

2. 开闭原则

对扩展开放,对修改关闭。

解释:软件实体(类、模块、函数等)应该允许扩展其行为,而不需要修改其源代码。通过继承、接口等方式实现扩展。

3.面向接口编程

使用接口而不是具体类来定义对象的行为。

解释:通过接口定义对象的行为,而不是依赖于具体实现,这样可以更容易地替换实现,提高代码的灵活性。

4. 封装变化点

将变化的部分封装起来,使其不影响其他部分。

解释:判断需求中的变化点,并将其封装在独立的模块中,这样可以减少变化对系统其他部分的影响。

5. 单一职责原则

职责,即变化;一个类或模块应该只有一个引起它变化的原因。

解释:每个类或模块应该只负责一个职责,这样可以提高代码的可维护性和可读性。

6. 里氏变换

子类可以替换父类,而不影响程序的正确性。

解释:子类应该能够替换父类,而不破坏程序的正确性。

7. 接口隔离

不应该强迫客户端依赖于它们不使用的接口。

解释:将大接口拆分为多个小接口,客户端只需要依赖于它们需要的接口,这样可以减少不必要的依赖。

8. 组合优于继承

优先使用组合而不是继承来实现代码复用。

解释:通过组合对象来实现代码复用,而不是通过继承,这样可以减少类之间的耦合,提高代码的灵活性。

9. 最小知道原则

一个对象应该对其他对象有尽可能少的了解。

解释:减少对象之间的依赖,降低耦合度,提高代码的可维护性和可扩展性。

二、设计模式

模版方法

1. 定义

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

2. 解决的问题

  • 稳定点:算法骨架
  • 变化点:子流程需要变换

3. 代码结构

  • 基类中有骨架流程接口
  • 所有子流程对子类开放并且是虚函数
  • 使用多态的方式

4. 符合哪些设计原则

单一职责

开闭

依赖倒置

  • 子类拓展时,需要依赖基类的虚函数实现
  • 使用者只依赖接口

封装变化点

  • protected 关键字

接口隔离

最小知道原则

5. 如何拓展

  • 实现子类继承基类,复写子流程
  • 通过多态方式进行调用

观察者模式

1. 定义

定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

2. 解决的问题

  • 稳定点:“一”对”多”的依赖关系;”一”变化,“多”也跟着变化;
  • 变化点:”多”增加;“多”减少

3. 代码结构

  • 定义一个 Subject 接口,包含 attachdetachnotify 方法。
  • 定义一个 Observer 接口,包含 update 方法。
  • Subject 类维护一个 Observer 列表,并在状态变化时通知所有观察者。

4. 符合哪些设计原则

面向接口编程:使用 SubjectObserver 接口定义行为。

接口隔离

  • 类与类依赖一个接口

封装变化点

5. 如何拓展

  1. 继承实现 Observer 接口
  2. 调用变化点封装函数

策略模式

1. 定义

定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。该模式使得算法可独立于使用它的客户程序而变化。

2. 解决的问题

  • 稳定点:客户程序与算法的调用关系
  • 变化点:新加算法;算法内容变动

3. 代码结构

  • 定义一个策略接口,包含算法的抽象方法。
  • 实现不同的策略类,每个类实现策略接口。
  • 客户程序通过依赖注入(传参)的方式使用策略。

4. 符合哪些设计原则

接口隔离

  • 依赖注入(传参)
  • 解决通过一个接口解决两个类的依赖

面向接口编程

开闭原则

5. 如何拓展

  • 实现新的策略类,继承策略接口。
  • 通过依赖注入的方式使用新的策略。