一.定义:
依赖倒置原则(Dependecy Inversion Principle)
原文为:
High level modules shouldnot depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details. Details should depend upon abstractions
三层定义:
1.高层模块不应该依赖底层模块。两者都应该依赖于抽象
有人翻译成低层我个人理解是底层:底层就是说某个抽象的实现类这样的就是具体的实现
2.抽象不应该依赖于细节
3.细节应该依赖抽象
三层定义的理解:
1.高层模块:调用方;底层模块:被调用方也就是实现类
有说高层就是抽象类,然而并不是这样子,高层可以是抽象类也可以是具体的类或者某一实现类,它掉用别人它就是高层
2.模块之间通过抽象关联,实现类之间不直接依赖:依赖都通过抽象或者接口
3.抽象和接口不依赖于实现类
4.实现类不依赖于抽象和接口
5.就是面向抽象或者接口编程:降低耦合度,降低并行开发引起的风险,提高可读性和可维护性
深入理解:
依赖倒置原则的本质就是面向接口编程,通过抽象使各个类和模块之间彼此独立,互不影响,实现松耦合,开发过程中具体规则如下:
1.每个类尽量使用抽象类或者接口,或者两者都有
2.任何类都需要充接口或者抽象类派生
3.尽量不要重写基类已经写好的方法(里氏替换原则)
4.结合里氏替换原则:
接口负责定义public属性和方法,并申明和其他对象的依赖关系(通过接口或者抽象依赖),抽象类负责公共构造部分,实现类实现业务
二.场景示例
场景1:用户用的小米手机现用酷狗软件听歌
1 public class KuGoMusic { 2 3 public void play(){ 4 System.out.println("heLlo kugo"); 5 } 6 } 7 8 public class XiaoMiPhone { 9 private KuGoMusic kuGoMusic; 10 11 public XiaoMiPhone(KuGoMusic kuGoMusic) { 12 this.kuGoMusic = kuGoMusic; 13 } 14 public void play(){ 15 kuGoMusic.play(); 16 } 17 }
需求变更:某天用户还想用QQ音乐,因为上面有酷狗没有的音乐,此时我们就需要修改小米手机类
1 public class XiaoMiPhone { 2 private KuGoMusic kuGoMusic; 3 private QQMusic qqMusic; 4 5 public XiaoMiPhone(KuGoMusic kuGoMusic, QQMusic qqMusic) { 6 this.kuGoMusic = kuGoMusic; 7 this.qqMusic = qqMusic; 8 } 9 10 public void playKugo(){ 11 kuGoMusic.play(); 12 } 13 public void playQQ(){ 14 qqMusic.play(); 15 } 16 }
如果用户还想使用网易音乐等等那么多音乐播放器,会造成 XiaoMiPhone这个类依赖的音乐类越来越多,代码越来越庞大
我们使用依赖倒置原则来优化代码
1.添加音乐接口;2.添加手机接口,增加对音乐接口的依赖
1 音乐接口 2 public interface IMusic { 3 public void play(); 4 } 5 手机抽象类 6 public abstract class IPhone { 7 private IMusic iMusic; 8 9 public IPhone(IMusic iMusic) { 10 this.iMusic = iMusic; 11 } 12 13 public void play(){ 14 iMusic.play(); 15 } 16 17 public abstract void call(); 18 } 19 手机实现类 20 public class RedMiPhone extends IPhone { 21 22 public RedMiPhone(IMusic iMusic) { 23 super(iMusic); 24 } 25 @Override 26 public void call() { 27 System.out.println("红米手机打电话"); 28 } 29 } 30 31 酷狗音乐 32 public class KuGoMusic implements IMusic{ 33 @Override 34 public void play(){ 35 System.out.println("heLlo kugo"); 36 } 37 } 38 39 public class QQMusic implements IMusic{ 40 @Override 41 public void play(){ 42 System.out.println("QQ music"); 43 } 44 } 45 46 public static void main(String[] args) { 47 IMusic kuGoMusic = new KuGoMusic(); 48 IMusic qqMusic = new QQMusic(); 49 System.out.println("我想使用酷狗"); 50 IPhone redMiPhone = new RedMiPhone(kuGoMusic); 51 redMiPhone.play(); 52 redMiPhone.call(); 53 System.out.println("============="); 54 System.out.println("我想使用qq音乐"); 55 redMiPhone = new RedMiPhone(qqMusic); 56 redMiPhone.play(); 57 redMiPhone.call(); 58 }
测试结果:实现了随心转换,不论以后增加多少种音乐都不需要去改动高层代码,只需要增加低层代码就OK了