设计模式之----依赖倒置(Dependency inversion principle)的理解

文章目录

      • 1.前言
      • 2.概念
        • 2.1 什么是依赖?
        • 2.2 什么是上层模块和下层模块?
        • 2.3 什么是抽象和细节?
      • 3.作用
      • 4.实现方法
      • 5.实例

1.前言

依赖倒置是面向对象设计领域的一种软件设计原则。 有人会有疑惑,设计原则有什么用呢?设计原则是前辈们总结出来的经验,你可以把它们看作是内功心法。只要你在平常开发中按照设计原则进行编码,假以时日,你编程的功力将会大增。

2.概念

依赖倒置原则的原始定义为:上层模块不应该依赖下层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象,其核心思想是:要面向接口编程,不要面向实现编程。这个是官方的定义,有些人一看可能是懵的!我们该怎么理解上面的定义呢?我们需要咬文嚼字,各个突破。


2.1 什么是依赖?

依赖是一种关系,通俗来讲就是一种需要,人钓鱼?人需要鱼竿钓鱼,因为人就没有鱼竿就钓不了鱼,,所以说人依赖鱼竿,鱼竿被人依赖。在面向对象编程中,代码可以这样编写。

class  fishing{
    private fishPole:fishPole;
    public fishing(){
        this.fishPole = new fishPole();
    }
}

fishing 的内部持有 fishPole 的引用,这就是依赖在编程世界中的体现。

2.2 什么是上层模块和下层模块?

俗话说,人人平等,但是为什么在同一个公司,你的工资就比你的上级领导工资要少呢?上级领导又比CEO要少呢?(对领导和你来说,那么上级领导就是上层,你就是下层,对于领导和CEO来说,CEO就是上层,领导就是下层),对于任何一个组织机构来说,它是有职能的划分的。按照职能的重要性,自然而然就有了上下之分。模块也是一样,也许某一模块相对于另外一模块它是下层,但是相对于其他模块它又可能是上层。

2.3 什么是抽象和细节?

抽象如其名字一样,是一件很抽象的事物。抽象往往是相对于具体而言的,具体也可以被称为细节,比如: 汽车就是抽象,而宝马520,奔驰E200,就是具体了,抽象可以是物是人也可以是行为!

3.作用

1. 可以降低类间的耦合性。
2. 可以提高系统的稳定性。
3. 可以减少并行开发引起的风险。
4. 可以提高代码的可读性和可维护性。

4.实现方法

使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给它们的实现类去完成。所以我们在实际编程中只要遵循以下4点,就能在项目中满足这个规则。

1. 每个类尽量提供接口或抽象类,或者两者都具备。
2. 变量的声明类型尽量是接口或者是抽象类。
3. 任何类都不应该从具体类派生。
4. 使用继承时尽量遵循里氏替换原则。

5.实例

一个非常简单的例子,小明目前是骑车去上学,此例子只是反映小明和车之间的依赖关系!

你可能会这么画类图

设计模式之----依赖倒置(Dependency inversion principle)的理解_第1张图片

//Xiaoming.ts
import { Bike } from "./Bike"

export class xiaoMing {
    private bike: Bike
    public goSchool() {
        this.bike = new Bike();
        this.bike.drive();
    }
}

//Bike.ts
export class Bike{
    public drive(){
        console.log("bike drive")
    }
}

某天,天空下雨了,小明不能骑自行车了,要做公交车了,然后你改代码

//Xiaoming.ts
import { Bike } from "./Bike"
import { Bus } from "./bus";
export class xiaoMing {
    private bike: Bike
    private bus: Bus
    public goSchool() {
        // this.bike = new Bike();
        this.bus = new Bus();
        this.bus.drive();
    }
}

又某天,小明要迟到了赶时间,小明要打的去学校,然后你改代码

//Xiaoming.ts
import { Bike } from "./Bike"
import { Bus } from "./Bus";
import { Taxi } from "./Taxi";

export class xiaoMing {
    private bike: Bike;
    private bus: Bus;
    private taxi: Taxi;
    public goSchool() {
        // this.bike = new Bike();
        // this.bus = new Bus();
        this.taxi = new Taxi();
        this.taxi.drive();
    }
}

类图就变成了这样
设计模式之----依赖倒置(Dependency inversion principle)的理解_第2张图片

这样每次添加一个类,你都要改代码,有没有一种方法能让 xiaoMing 的变动少一点呢?因为这是最基础的演示代码,如果工程大了,代码复杂了,xiaoMing 面对需求变动时改动的地方会更多。而依赖倒置原则正好适用于解决这类情况。先看下类图

设计模式之----依赖倒置(Dependency inversion principle)的理解_第3张图片

我们的代码中,xiaoMing是个具体类,所以它需要一个Person接口, xiaoMing没有依赖抽象,所以我们得引进抽象。而底层的抽象是什么,是 Driveable 这个接口。


//Person.ts
export interface Person {
    goSchool();
}

//Driveable.ts
export interface Driveable {
    drive();
}

//Bike.ts
import { Driveable } from "./Driveable";

export class Bike implements Driveable{
    public drive(){
        console.log("bike drive")
    }
}

//Bus.ts
import { Driveable } from "./Driveable";

export class Bus implements Driveable{
    public drive(){
        console.log("bus drive")
    }
}

//Taxi.ts
import { Driveable } from "./Driveable";

export class Taxi implements Driveable{
    public drive(){
        console.log("taxi drive")
    }
}

//xiaoMing.ts
import { Driveable } from "./Driveable";
import { Person } from "./Person";

export class xiaoMing implements Person {
    private drive;
    constructor(drive: Driveable) {
        this.drive = drive;
    }
    public goSchool() {
        this.drive.drive();
    }
}

//外层调用
let xiaoM = new xiaoMing(new Bus());
xiaoM.goSchool();

xiaoMing类中 drive() 这个方法依赖于 Driveable 接口的抽象,它没有限定自己出行的可能性,任何 Car、Bike 或者是 Bus都可以的。我们可以说是符合了上层不依赖于底层,依赖于抽象的准则了。那么,抽象不应该依赖于细节,细节应该依赖于抽象又是什么意思呢?Driveable 是抽象,它代表一种行为,而 Bike、Car、Bus都是实现细节。如果我改变了实现细节里面的逻辑代码是不会影响到Driveable 抽象,然后我改了Driveable抽象必然会影响到细节的实现,所以说抽象不应该依赖于细节,细节应该依赖于抽象!关系变化如图:
设计模式之----依赖倒置(Dependency inversion principle)的理解_第4张图片设计模式之----依赖倒置(Dependency inversion principle)的理解_第5张图片

不难发现,上面的依赖箭头发生了改变。所以依赖倒置也由此而来,上层模块xiaoMing不应该依赖下层bike模块,它们都应该依赖于抽象Driveable。依赖倒置我们可以理解为依赖关系被改变,倒置的其实是下层细节,原本它是被上层依赖,现在它倒要依赖与抽象的接口,所以说依赖倒置实质上是面向接口编程的体现。

你可能感兴趣的:(设计模式,依赖倒置原则)