设计模式中常见原则(未完成)

设计模式中常见原则

1.1 单一职责原则

单一职责原则(Single-Responsibility Principle,SRP),就一个类而言,应该仅有一个引起它变化的原因。

设计理由:职责耦合,难以维护:如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。

发现职责并把这些职责相互分离,如果能想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责,就应该考虑是否进行职责分离。

1.2 开放-封闭原则

开放-封闭原则(The Open-Closed Principle,OCP),指软件的实体如类、模块和函数等,应该可以扩展,但是不可修改。

开放-封闭原则的两个特征:

  • 对于扩展是开放的,Open for extension
  • 对于更改是封闭的,Closed for modification
  • 背景:我们在开发项目时不能指望需求是一定不会变的,这是不现实的。而需求的变化就意味着一定会有开销,所以面对一定会变化的需求,我们需要设计容易修改的系统
  • 开发-封闭原则的本意并非是让我们未卜先知,事先猜想到需求会发生的变化,而是专注于设计好当前的类,当需求变更时,尽量不要动这些部分。无论模块多么“封闭”,都会存在一些无法对之封闭的变化,既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择,必须猜出最有可能发生的变化种类,然后构造抽象来隔离这些变化。预测变化是很难的,但我们可以等到变化发生时立即采取行动,创建抽象来隔离以后发生的同类变化,至少做到不栽在同一个坑里。所以设计时尽量切分抽象层实现层,不修改抽象,只扩展实现。
  • 当面对需求变化时,对程序的改动是通过增加新代码进行的,而不是破坏现有的代码。
  • 开放-封闭原则是面向对象设计的核心所在,遵循这个原则可以带来面向对象技术所声称的巨大好处,即可维护、可扩展、可复用和高灵活性。开发人员应该仅对程序中呈现出频繁变化的哪些部分做出抽象,因为对于应用程序中的每个部分都刻意的进行抽象并不是一个好主意,拒绝不成熟的抽象和抽象本身一样重要。

1.3 里氏代换原则

一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。也就是说,在软件里面,把父类都替换为其子类,程序的行为不会变化

里氏代换原则:子类型必须能够替换掉它们的父类型

只有当子类可以替换掉父类,软件单位的功能不受影响时,父类才能真正的被复用,而子类也能够在父类的基础上增加新的行为。

1.4 依赖倒转原则

抽象不应该依赖于细节,细节应该依赖于抽象。即要针对接口编程,不要对实现编程。

依赖倒转原则:

  • 高层模块不应该依赖低层模块,两个都应该依赖于抽象。
  • 抽象不应该依赖于细节,细节应该依赖于抽象。

我们日常开发时,为了提高代码复用,会切出一些函数库,这样每次新项目开发只要调用这些低层的函数即可,这也叫高层模块依赖低层模块。但这样的结构会因为依赖关系使高层模块和低层模块绑定在一起,难以复用,比如我们需要变更数据库,我们本应该只修改访问数据库部分,但高层调用和数据库访问绑定在一起,难以复用这些高层模块。

1
2
3
---------            ---------         
|高层模块| ------> |低层模块|
--------- ---------

根据里氏代换原则,由于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展,所以应该采用以下结构。

1
2
3
4
5
6
7
8
9
10
---------    调用     -------------        
|高层模块| ------> |接口或抽象类|
--------- -------------
^
|
|
|
---------
|低层模块|
---------

依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或接口,那就是面向对象的设计,反之就是过程化的设计。

1.5 迪米特法则

迪米特法则(LoD),也叫最少知识原则,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

  1. 只和直接的朋友交流:对于类来说,直接朋友就是出现在成员变量、函数输入输出中的其它类。而只出现与函数内部的则不是直接的朋友。对于这种朋友,应该放在第三个类中做相关处理。
  2. 减少对朋友的了解:对于类来说,就是尽量减少类对外暴露的内容,将大部分细节封装,设为私有。

类的结构设计上,每一个类都应当尽量降低成员的访问权限,也就是面向对象封装的思想,强调了类之间的松耦合,类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。


参考:

🔗 《设计模式:可复用面向对象软件的基础》
🔗 《大话设计模式》