依赖倒转(倒置)原则
1、高层模块不应该依赖底层模块,二者都应该依赖其抽象;
2、抽象不应该依赖细节,细节应该依赖抽象;
3、依赖倒转原则的核心思想是:要面向接口便车鞥,不要面向实现编程;
4、依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象则相对稳定。以抽象为基础搭建的架构比以细节为基础的结构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类。
5、使用接口或抽象类的目的是制定好规范和契约,而不涉及任何具体的操作,把展现细节的任务交给它们的实现类去完成。
依赖倒转原则的实现方法:
1、每个类尽量提供接口或抽象类,或者两者都具备。
2、变量的生命类型尽量是接口或者是抽象类。
3、任何类都不应该从具体类派生。
4、使用继承时尽量遵循里式替换原则。
依赖关系传递的三种方式:
接口传递、构造方法传递、setter方式传递。
案例:
public class DependenceInversion { public static void main(String[] args) { Person person = new Person(); person.receive(new Email()); } } /** * 邮件类 */ class Email{ public String getInfo(){ return "电子邮件信息:hello,world!"; } } /** * person接受消息的功能 * 简单,易想到 * 问题:如果获取的对象是微信,短信等,则需要新增类,同时person类也需要增加相应的接受方法。 * 解决:引入一个抽象的接口IReceiver,表示接受者,这样person类与接口发生依赖 * 因为微信,短信等都属于接收的范围,他们各自实现IReceiver接口,这样就符合依赖倒转原则。 */ class Person{ public void receive(Email email){ System.out.println(email.getInfo()); } }
使用依赖转换原则改进:
public class DependenceInversion { public static void main(String[] args) { Person person = new Person(); person.receive(new Email()); person.receive(new WeiXin()); } } interface IReceiver{ public String getInfo(); } /** * 邮件类 */ class Email implements IReceiver{ public String getInfo(){ return "电子邮件信息:hello,world!"; } } class WeiXin implements IReceiver{ @Override public String getInfo() { return "微信消息:hello,world!"; } } class Person{ public void receive(IReceiver receiver){ System.out.println(receiver.getInfo()); } }
依赖关系传递的三种方式:
public class DependencyPass { public static void main(String[] args) { /*方式一*/ ChangHong changHong = new ChangHong(); new OpenAndClose().open(changHong); /*方式二*/ new OpenAndClose2(new ChangHong2()).open(); /*方式三*/ OpenAndClose3 openAndClose3 = new OpenAndClose3(); openAndClose3.setITV3(new ChangHong3()); openAndClose3.open(); } } /*方式一:通过接口传递实现依赖*/ //开关的接口 interface IOpenAndClose { //抽象方法,接收接口 public void open(ITV itv); } //ITV接口 interface ITV { public void play(); } //实现接口 class OpenAndClose implements IOpenAndClose { @Override public void open(ITV itv) { itv.play(); } } //实例化 class ChangHong implements ITV { @Override public void play() { System.out.println("长虹电视机打开"); } } /*方式二:通过构造方法传递依赖*/ interface IOpenAndClose2 { public void open(); } interface ITV2 { public void play(); } class OpenAndClose2 implements IOpenAndClose2 { private ITV2 itv2; public OpenAndClose2(ITV2 itv2) { this.itv2 = itv2; } @Override public void open() { itv2.play(); } } //实例化 class ChangHong2 implements ITV2{ @Override public void play() { System.out.println("长虹电视机2打开"); } } /*方式3:通过setter方法传递依赖*/ interface IOpenAndClose3 { public void open(); public void setITV3(ITV3 itv3); } interface ITV3 { public void play(); } class OpenAndClose3 implements IOpenAndClose3 { private ITV3 itv3; @Override public void open() { itv3.play(); } @Override public void setITV3(ITV3 itv3) { this.itv3 = itv3; } } //实例化 class ChangHong3 implements ITV3{ @Override public void play() { System.out.println("长虹电视机3打开"); } }