面向对象编程五大原则SOLID-里氏替换原则、接口隔离原则、依赖倒置原则

809 阅读3分钟

里氏替换原则:LSP(The Liskov Substitution Principle)

子类型(subtype)必须能够替换其父类型(base type)。

Derived classes must be substitutable for their base classes.

这里需要如下替换性质:若每个类型 S 的对象 o1,都存在一个类型 T 的对象 o2,使得在所有针对 T 编程的程序 P 中,用 o1 替换 o2 后,程序 P 行为保持不变,则 S 是 T 的子类型。

用通俗的讲法来说,意思就是,子类型(subtype)必须能够替换其父类型(base type)。

  1. 如果你发现了任何做运行时类型识别的代码,此时你就需要思考一下,是否违反了里氏替换原则。typeof(baseClass) == AClass
  2. 定义了一个接口,某一个子类无法实现接口的行为。导致执行逻辑报错,这也违反里氏替换原则。IS-A 的判定是基于行为的

接口隔离原则:ISP(The Interface Segregation Principle)

不应强迫使用者依赖于它们不用的方法。

No client should be forced to depend on methods it does not use.

依赖倒置原则:DIP(The Dependency Inversion Principle)

高层模块不应依赖于低层模块,二者应依赖于抽象。

High-level modules should not depend on low-level modules. Both should depend on abstractions.

抽象不应依赖于细节,细节应依赖于抽象。

Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.

计算机科学中的所有问题都可以通过引入一个间接层得到解决。All problems in computer science can be solved by another level of indirection—— David Wheeler

高层模块不依赖于低层模块,可以通过引入一个抽象,或者模型,将二者解耦开来。高层模块依赖于这个模型,而低层模块实现这个模型。

DIP、IoC、DI

说起DI不得不提IoC这个模式,很多人会把DI和IoC混为一谈,但其实这两者是概念和实现的关系。关于 DIP,还有一个形象的说法,称为好莱坞规则:“Don’t call us, we’ll call you”。放在设计里面,这个翻译应该是“别调用我,我会调你的”。显然,这是一个框架才会有的说法,有了一个稳定的抽象,各种具体的实现都应该是由框架去调用。

依赖倒置原则(DIP):软件设计原则,要依赖于抽象,不要依赖具体实现。 控制反转(IoC:Inverse of Control):一种实现DIP原则的模式。 依赖注入(DI: Dependency Injection):IoC的具体实现。

.Net DI框架Autofac

引入DI框架的好处

  • 所有组件、对象的生命周期都交给容器处理。能解决发现复杂的依赖关系,如循环依赖
  • 高层模块和底层模块依赖接口,对于后期变化,如将mysql替换为cassandra,我们只需要实现一套Cassandra的服务的接口,在容器注册中将mysql替换。
  • 当所有模块依赖都为接口时,我们就可以更容易去编写单元测试,我们可以通过Mock框架去Mock所依赖的组件。如果依赖的是实例,我们很难去写测试。