面向对象的7种设计原则(3)-依赖倒置原则

    技术2025-02-02  9

    依赖倒置原则

    High level modules should not depend upon low level modules.Both should depend upon abstractions. 高层模块不应该依赖低层模块,两者都应该依赖其抽象(模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的)Abstractions should not depend upon details. 抽象不应该依赖细节(接口或抽象类不依赖于实现类)Details should depend upon abstractions. 细节应该依赖抽象(实现类依赖接口或抽象类)

    经典案例

    三年二班有个同学闰土,想要学习Java,于是他买了一本《Java从入门到放弃》

    class Runtu { public void study(Java java){ java.bookName(); } } class Java{ public void bookName(){ System.out.println("《Java从入门到放弃》"); } } class Program{ public static void main(String[] args) { Runtu runtu = new Runtu(); Java java =new Java(); runtu.study(java); } }

    过了一段时间,闰土java学完了,又想学习一下《Linux从删库到跑路》

    class Runtu { public void study(Java java) { java.bookName(); } public void study(Linux linux) { linux.bookName(); } } class Java { public void bookName() { System.out.println("《Java从入门到放弃》"); } } class Linux { public void bookName() { System.out.println("《Linux从删库到跑路》"); } } class Program { public static void main(String[] args) { Runtu runtu = new Runtu(); Java java = new Java(); Linux linux = new Linux(); runtu.study(java); runtu.study(linux); } }

    闰土除了抓猹看西瓜地外,学习新技术也很快,很快这2本都学完了。听说前端的Vue很火,梦想成为一个看西瓜的人中技术最好的仔的闰土就又买了一本《Vue从入门到崩溃》,如果继续按上面的模式,随着闰土的不断学习,我们的代码却越来越臃肿,变得难以维护。 由于RunTu是一个高级模块并且是一个细节实现类,此类依赖了书籍Java和Linux又是一个细节依赖类,这导致RunTu每读一本书都需要修改代码,这与我们的依赖倒置原则是相悖的。 闰土也意识到了这一点,买了一本《设计模式》看了看,然后改成了下边的代码:

    class Runtu { void study(IBook iBook) { iBook.bookName(); } } abstract class IBook{ abstract void bookName(); } class Java extends IBook{ void bookName() { System.out.println("《Java从入门到放弃》"); } } class Linux extends IBook{ void bookName() { System.out.println("《Linux从删库到跑路》"); } } class Program { public static void main(String[] args) { Runtu runtu = new Runtu(); Java java = new Java(); Linux linux = new Linux(); runtu.study(java); runtu.study(linux); } }

    我们发现,只要让RunTu依赖于抽象IBook,其他书籍依赖于该抽象,以后不管闰土读什么书,都不会放弃跑路了。

    依赖关系传递的三种方式

    通过接口和抽象类传递

    class Runtu { void study(IBook iBook) { iBook.bookName(); } }

    通过构造方法传递

    class Runtu { private IBook iBook; public Runtu(IBook iBook) { this.iBook = iBook; } void study() { this.iBook.bookName(); } }

    通过Setter方法传递

    class Runtu { private IBook iBook; public void setiBook(IBook iBook) { this.iBook = iBook; } void study() { this.iBook.bookName(); } }

    总结

    依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合。我们在项目中使用这个原则要遵循下面的规则:

    每个类尽量都有接口或者抽象类,或者抽象类和接口两都具备

    变量的表面类型尽量是接口或者抽象类

    任何类都不应该从具体类派生

    尽量不要覆写基类的方法

    如果基类是一个抽象类,而这个方法已经实现了,子类尽量不要覆写。类间依赖的是抽象,覆写了抽象方法,对依赖的稳定性会有一定的影响

    个人博客 腾讯云社区 掘金 简书 GitHub 码云 OSCHINA Segmentfault 公众号:

    Processed: 0.010, SQL: 9