Jinyun's Notes

没什么天赋,爱好也不多,但愿坚持做些喜欢的事情

0%

设计模式六大原则

单一职责原则

单一职责原则 - SRP: Single Responsibility Principle

实现类要职责单一。

单一职责定义

不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。

单一职责问题由来

类 T 负责两个不同的职责:职责 P1,职责 P2。当由于职责 P1 需求发生改变而需要修改类 T 时,有可能会导致原本运行正常的职责 P2 功能发生故障。

单一职责注意点

  • 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多
  • 提高类的可读性,提高系统的可维护性
  • 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响

里氏替换原则

里氏替换原则 - LSP: Liskov Substitution Principle

不要破坏继承体系。

里氏替换定义

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

里氏替换问题由来

有一功能 P1,由类 A 完成。现需要将功能 P1 进行扩展,扩展后的功能为 P,其中 P 由原有功能 P1 与新功能 P2 组成。新功能 P 由类 A 的子类 B 来完成,则子类 B 在完成新功能 P2 的同时,有可能会导致原有功能 P1 发生故障。

里氏替换注意点

里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
  • 子类中可以增加自己特有的方法
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松
  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格

依赖倒置原则

依赖倒置原则 - DIP: Dependence Inversion Principle

面向接口编程。

依赖倒置定义

高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。

依赖倒置问题由来

类 A 直接依赖类 B,假如要将类 A 改为依赖类 C,则必须通过修改类 A 的代码来达成。这种场景下,类 A 一般是高层模块,负责复杂的业务逻辑;类 B 和类 C 是低层模块,负责基本的原子操作;假如修改类 A,会给程序带来不必要的风险。

依赖倒置注意点

  • 低层模块尽量都要有抽象类或接口,或者两者都有
  • 变量的声明类型尽量是抽象类或接口
  • 使用继承时遵循里氏替换原则

接口隔离原则

接口隔离原则 - ISP: Interface Segregation Principle

  • 设计接口的时候要精简单一
  • 多用组合,少用继承,Has 关系组合,Is 关系继承

接口隔离定义

客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。

接口隔离问题由来

类 A 通过接口 I 依赖类 B,类 C 通过接口 I 依赖类 D,如果接口 I 对于类 A 和类 B 来说不是最小接口,则类 B 和类 D 必须去实现他们不需要的方法。

将臃肿的接口 I 拆分为独立的几个接口,类 A 和类 C 分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。

接口隔离注意点

  • 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不争的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度
  • 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系
  • 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情

迪米特法则

迪米特法则 - LKP: Least Knowledge Principle

降低耦合只与直接的朋友通信。

迪米特法则定义

一个对象应该对其他对象保持最少的了解。

迪米特法则问题由来

类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。

尽量降低类与类之间的耦合。

迪米特法则注意点

  • 过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大
  • 在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合

开闭原则

开闭原则 - OCP: Open Closed Principle

扩展开放,对修改关闭。

开闭原则定义

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

开闭原则问题由来

在软件的生命周期内,因为变化 / 升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。

当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

开闭原则注意点

  • 用抽象构建框架,用实现扩展细节
  • 抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定
  • 而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了
本笔记是笔者在学习和工作中的一些整理,如对您有用,请鼓励我继续写作