【依赖倒置原则 - 六大设计原则 - 设计模式】

4,116 阅读3分钟

依赖倒置原则(Dependence Inversion Principle)

依赖倒置原则是指在设计代码架构时,高层模块不应该依赖底层模块,二者都该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象

  • 传统的自顶向下设计

传统设计方式采用自顶向下的原则, 逐级依赖,中层模块和高层模块的耦合度很高,如果需要修改其中的一个模块,则可能会导致其它很多模块也需要修改,牵一发动全身,不易于维护。 不使用依赖反转的系统构架,控制流和依赖关系流的依赖箭头是一个方向的,由高层指向底层,也就是高层依赖底层

截屏2023-01-10 22.32.50.png

  • 依赖倒置原则

依赖倒置原则的好处:

  • 减少类之间的耦合性,提高系统的稳定性。(根据类与类之间的耦合度从弱到强排列:依赖关系、关联关系、聚合关系、组合关系、泛化关系和实现关系)
  • 降低并行开发引起的风险(两个类之间有依赖关系,只有指定两者之间的接口(或抽象类)就可以独立开发了)
  • 提高代码的可读性和可维护性

截屏2023-01-10 22.33.20.png

场景示例

假如我们现在简单的装修房子,需要配备一台电视、冰箱、煮饭用的锅

截屏2023-01-10 22.49.50.png

代码如下:

冰箱类(HaierRefrigerator)

class HaierRefrigerator: Refrigerator {
    func work() {
        print("Make food refresh")
    }
}

电视类(XiaoMiTV)

class XiaoMiTV: TV {
    func show() {
        print("look tv")
    }
}

锅类(ZwillingPot)

class ZwillingPot: Pot {
    func cook() {
        print("Cooking")
    }
}

家(Home)

class Home {
    var refrigerator: HaierRefrigerator
    var tv: XiaoMiTV
    var pot: ZwillingPot

    init(refrigerator: HaierRefrigerator, tv: XiaoMiTV, pot: ZwillingPot) {
        self.refrigerator = refrigerator
        self.tv = tv
        self.pot = pot
    }

    func live() {
        print("Live in home")
        refrigerator.work()
        tv.show()
        pot.cook()
    }
}

测试类(TestHome)

测试类用来组装家

class TestHome {
    func test() {
        let home = Home(refrigerator: HaierRefrigerator(), tv: XiaoMiTV(), pot: ZwillingPot())
        home.live()
    }
}

上门代码可以看到组合来一个简单的家,但是组装的TV只可以用xiaomi,冰箱只可以用海尔,锅只可以用双立人,但是实际装修时,并不是这样,有的人喜欢苹果的tv,有的人喜欢WFM的锅,这样对装修的人不友好,装修的用户是可以按照自己的喜好来配置配件。

根据依赖倒置原则进行改进: 代码我们需要修改Home类,让Home类依赖抽象(各个家具配件的接口),而不是依赖于各个组件的具体实现类。

类图如下

截屏2023-01-10 23.06.45.png

Home类(Home)

class Home {
    var refrigerator: Refrigerator
    var tv: TV
    var pot: Pot

    init(refrigerator: HaierRefrigerator, tv: XiaoMiTV, pot: ZwillingPot) {
        self.refrigerator = refrigerator
        self.tv = tv
        self.pot = pot
    }

    func live() {
        print("Live in home")
        refrigerator.work()
        tv.show()
        pot.cook()
    }
}

关于依赖倒置、依赖注入、控制反转这二者的区别与联系

  1. 依赖倒置原则 依赖倒置是一种通用的软件设计原则,主要用来指导框架层面的设计。

高层模块不依赖底层模块,它们共同依赖同一个抽象。抽象不要依赖具体实现细节,具体实现细节依赖抽象。

  1. 控制反转 控制反转与依赖倒置有一些相似,它也是一种框架设计常用的模式,但并不是具体的方法。

"控制"指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序猿自己控制整个程序的执行。在使用框架之后,整个程序的执行流程通过框架来控制。流程的控制权从程序猿“反转”给了框架。

  1. 依赖注入 依赖注入是实现控制反转的一个手段,它是一种具体的编程技巧。

我们不通过 new 的方式在类内部创建依赖的对象,而是将依赖的对象在外部创建好之后,通过构造函数等方式传递(或注入)进来,给类使用。 依赖注入真正实现类面向接口编程的愿景,可以很方便地替换同一接口的不同实现,而不会影响到依赖这个接口的客户端

Dependence Inversion Principle