所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体。实现开闭原则的关键是抽象化,并且从抽象化导出具体化实现,如果说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要手段。
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
通俗点说:要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。
依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
依赖倒置原则的核心思想是面向接口编程,我们依旧用一个例子来说明面向接口编程比相对于面向实现编程好在什么地方。场景是这样的,厨师要做蛋炒饭,本来用鸡蛋的,后来客户需求变了,要使用鹌鹑蛋。代码如下:
package principle.dependence_inversion_principle;
import org.junit.Test;
/**
* 3.依赖倒置原则 (Dependence Inversion Principle)
*
* 所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体。实现开闭原则的关键是抽象化,并且从抽象化导出具体化实现,如果说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要手段。
*
* 定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
*
* 通俗点说:要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
*
* 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
*
* 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。
*
* 依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
*/
public class Client {
@Test
public void test(){
Cook cook = new Cook("李厨师");
cook.fryRice(new ChickenEgg("鸡蛋"));//蛋炒饭 蛋采用鸡蛋
//打印信息: 李厨师 正在做 鸡蛋炒饭
//新的需求,改用鹌鹑蛋,如果依赖类,还需要修改cook类,若依赖接口,cook类就需要修改
cook.fryRice(new QuailEgg("鹌鹑蛋"));//蛋炒饭 蛋采用鹌鹑蛋
//打印信息: 李厨师 正在做 鹌鹑蛋炒饭
}
}
package principle.dependence_inversion_principle;
/**
* 厨师类
*/
public class Cook {
private String name;
public Cook(String name) {
this.name = name;
}
public void fryRice(IEgg egg){
System.out.println(String.format("%s 正在做 %s炒饭",this.name,egg.getName()));
}
// public void fryRice(QuailEgg egg){
// System.out.println(String.format("%s 正在做 %s炒饭",this.name,egg.getName()));
//
// }
}
package principle.dependence_inversion_principle;
/**
* 原材料接口 蛋
*/
public interface IEgg {
public String getName();
}
package principle.dependence_inversion_principle;
/**
* 原材料实现类 鸡蛋
*/
public class ChickenEgg implements IEgg{
private String name ;
public ChickenEgg(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
package principle.dependence_inversion_principle;
/**
* 原材料实现类 鹌鹑蛋
*/
public class QuailEgg implements IEgg{
private String name ;
public QuailEgg(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
六大设计原则: