一、依赖倒转原则
基本原则
高层模块不应该依赖底层模块,二者都应该依赖其抽象
抽象不应该依赖细节,细节应该依赖抽象
依赖倒转的中心思想是面向接口编程
设计理念
相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类
使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成
代码对比
代码一:
public class A { public static void main(String[] args) { Person person = new Person(); person.receive(new Email()); } } class Email{ public String getInfo(){ return "电子邮箱:我是一棵卷心菜"; } } class Person { public void receive(Email email){ System.out.println(email.getInfo()); } }
代码一比较简单,容易想到。但是如果我们获取的对象是其它的,比如QQ,就需要在Person类中增加相应的接收方法,接下来看看代码二是如何解决这样的问题
代码二:
public class B { public static void main(String[] args) { Man man = new Man(); man.receive(new QQ()); } } interface Receiver{ String info(); } class QQ implements Receiver{ public String info() { return "用QQ接收信息"; } } class WeChat implements Receiver{ public String info() { return "用WeChat接收信息"; } } class Man{ public void receive(Receiver receiver){ System.out.println(receiver.info()); } }
代码二引入一个抽象的接口Receiver,这样Man类与接口发生了依赖
二、依赖关系传递
方式一:接口传递
代码实现:
public class C { public static void main(String[] args) { ChangHong changHong = new ChangHong(); OpenAndClose openAndClose = new OpenAndClose(); openAndClose.open(changHong); } } //开关的接口 interface IOpenAndClose { void open(ITV tv); //抽象方法,接收接口 } //ITV接口 interface ITV { void play(); } class ChangHong implements ITV { @Override public void play() { System.out.println("打开长虹电视机"); } } // 实现接口 class OpenAndClose implements IOpenAndClose{ public void open(ITV tv){ tv.play(); } }
可以看到,接口IOpenAndClose 的方法中,引用了接口ITV ,实现了接口的传递,简化了代码
方式二:构造方法传递
代码实现
public class C { public static void main(String[] args) { ChangHong changHong = new ChangHong(); OpenAndClose openAndClose = new OpenAndClose(changHong); openAndClose.open(); } } class ChangHong implements ITV { @Override public void play() { System.out.println("打开长虹电视机"); } } interface IOpenAndClose { void open(); //抽象方法 } interface ITV { //ITV接口 void play(); } class OpenAndClose implements IOpenAndClose { public ITV tv; public OpenAndClose(ITV tv) { this.tv = tv; } public void open() { this.tv.play(); } }
通过创建OpenAndClose 的对象时,把changHong 这个对象放在构造器中,同时呢,ChangHong类又实现了ITV 接口,通过构造器的方法实现关系传递,非常的巧妙
方式三:setter方式传递
代码实现:
public class C { public static void main(String[] args) { ChangHong changHong = new ChangHong(); OpenAndClose openAndClose = new OpenAndClose(); openAndClose.setTv(changHong); openAndClose.open(); } } interface IOpenAndClose { void open(); void setTv(ITV tv); } interface ITV { void play(); } class OpenAndClose implements IOpenAndClose { private ITV tv; public void setTv(ITV tv) { this.tv = tv; } public void open() { this.tv.play(); } } class ChangHong implements ITV { public void play() { System.out.println("打开长虹电视机"); } }
代码三比较好理解,接口IOpenAndClose 中写一个方法void setTv(ITV tv),就把接口ITV放进去了,也达到了依赖关系的传递
以上代码的运行结果都是一样的: