依赖倒转原则
定义:高层模块不应该依赖底层模块,二者都应该依赖其抽象;
总结:
1.抽象不应该依赖细节,细节应该依赖抽象;
2.针对接口编程,不要针对实现编程;
优点:可以减少类间的耦合性、提高系统稳定性,提高代码可读性和可维护性,可降低修改程序所造成的风险
二、代码
下面进入代码演示阶段:
场景模拟:一个用于定义行为的接口,多个实现接口不同行为的类,一个使用不同行为实现类的操作;
简单说,工厂生产了一种制造冰箱的机器,美的与海尔分别用来生产自己品牌的冰箱,商场来买这两个品牌的冰箱;
工厂:接口
美的-海尔:实现
商场:使用者
代码演示一:
1、接口定义行为
/**
* 服务提供制定接口
*/
public interface IBook {
public void salebook();
}
2、不同行为实现
//实现一
public class JavaBook implements IBook {
@Override
public void salebook() {
System.out.println("销售java相关书籍");
}
}
//实现二
public class PythonBook implements IBook{
@Override
public void salebook() {
System.out.println("销售python类型书籍");
}
}
3、行为调用
/**
* 销售员
*/
public class SalePerson {
/**
* 销售java书籍
*/
public void javaSaleBook(){
new JavaBook().salebook();
}
/**
* 销售python书籍
*/
public void pythonSaleBook(){
new PythonBook().salebook();
}
}
4、测试
/**
* 测试类
*/
public class MainTest {
public static void main(String[] args) {
SalePerson sp = new SalePerson();
sp.javaSaleBook();
sp.pythonSaleBook();
}
}
总结:上面的简单例子是典型底层实现功能,上层(main方法测试)调用,每次的需求添加都要在底层添加不同的行为;假如此时扩展了一个国美冰箱,那么销售员类里需要添加一个国美冰箱的销售方法,上层采用调用;
代码演示二:
1、修改销售执行函数,由上层传入不同的类型来决定最终的执行效果
package com.cjy.design.principle.dependenceinversion;
/**
* 销售员
*/
public class SalePerson {
/**
* 销售java书籍
*/
/* public void javaSaleBook(){
new JavaBook().salebook();
}
*//**
* 销售python书籍
*//*
public void pythonSaleBook(){
new PythonBook().salebook();
}*/
//调整执行函数
public void saleBook(IBook iBook){
iBook.salebook();
}
}
2、测试调用效果
public static void main(String[] args) {
SalePerson sp = new SalePerson();
sp.saleBook(new JavaBook());
sp.saleBook(new PythonBook());
}
总结:用上层main来决定调用执行效果
代码演示三:
上层决定调用方式,通过构造器传入参数
1、修改执行调用类
package com.cjy.design.principle.dependenceinversion;
/**
* 销售员
*/
public class SalePerson {
private IBook iBook;
public SalePerson(IBook iBook){
this.iBook=iBook;
}
public void saleBook(){
iBook.salebook();
}
}
2、调用测试
public static void main(String[] args) {
SalePerson sp = new SalePerson(new JavaBook());
sp.saleBook();
}
总结:这种方式一个执行对象只能执行一种类型的操作,因为他是通过构造器传入的执行类型
代码演示四:
1、修改执行调用
package com.cjy.design.principle.dependenceinversion;
/**
* 销售员
*/
public class SalePerson {
private IBook iBook;
public SalePerson(){
}
public void saleBook(){
iBook.salebook();
}
public void setiBook(IBook iBook){
this.iBook=iBook;
}
}
2、调用测试
public static void main(String[] args) {
SalePerson sp = new SalePerson();
sp.setiBook(new PythonBook());
sp.saleBook();
//-----------
sp.setiBook(new JavaBook());
sp.saleBook();
}
总结:依赖倒转我的理解就是原本底层实现好功能,由上层来调用,上层调用什么功能有底层来决定,依赖倒转则是打破这种方式,底层封装好功能后上层调用什么功能由上层自己来决定。
上面演示的四种方式:后面三种全是依赖倒转原则,第三种由于是构造器传入类型则受限制与一个对象执行执行一种功能,二与四则一个对象可调用多个,我倾向于方式四;