【1.2】依赖倒置原则

说到依赖倒置原则,肯定很多人比较迷糊了,什么是依赖?为什么还要倒置?依赖倒置有啥有点?

下面我们从依赖倒置原则得定义,实现方式等角度具体来说下。

一、定义

依赖倒置得原始定义是:

High level modules should not depend upon low level modules,Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstracts.

翻译过来的意思,包括以下三点:

1、高级模块不应依赖底层模块,两者都应依赖其抽象。

2、抽象不应该依赖其细节。

3、细节应该依赖其抽象。

高级模块和低层模块是什么意思呢?

一般我们的逻辑的实现都是由不可再分的原子逻辑组成,那么这个不可再分的原子逻辑就是低层模块,而由原子逻辑再组装的模块就是高级模块。

抽象很好理解,比较我们JAVA都是面向对象编程。抽象一般是指接口或者抽象类,两者都不能直接被实例化。而细节,就是其实现类。

那么我们现在再来看看依赖倒置的意思,他在JAVA上表现出来的意思就是:

1、模块间的依赖,通过抽象发生,实现类之间不能直接发生依赖关系,实现类之间的依赖关系是通过接口或者抽象类实现的。

2、接口或者抽象类不应该依赖实现类。

3、实现类要依赖接口或者抽象类。

二、我们为什么要使用依赖倒置?

编程时,我们常常会想我们为什么需要使用依赖倒置?依赖倒置有啥好处?

讲好处之前我们不妨先说说不使用依赖倒置的坏处。

我们构建一个驾驶员开车的场景:

【1.2】依赖倒置原则_第1张图片

如上图,我们可以看到,驾驶员开始得需要驾驶员(driver)类,和汽车类(car)。

Driver:

//驾驶员
public class Driver {
    void driver(CarBenz car){
        car.run();
    }
}

Car:

//汽车类
public class CarBenz {
    void run(){
        System.out.println("开奔驰咯。。。");
    }
}

开车:

import org.springframework.context.annotation.Bean;

public class Test {
    public static void main(String[] args){
        Driver driver = new Driver();
        CarBenz benz = new CarBenz();
        driver.driver(benz);
    }
}

输出结果为:

开奔驰咯。。。

看了上面的代码,似乎我们不用依赖倒置也是可以开车,实现驾驶的功能。

但是,生活毕竟是生活,我总不能只开这一辆车吧?如果我想换车开,怎么办?是不是就得改写driver里的方法?如果我不定期增加呢?是不是driver会越扩越大?

而且,这还不是最头疼的,如此写法,driver高度依赖Car,我们正常研发的话,如果A程序员研发driver,B程序员研发Car。那么A程序员必须等到B程序员研发完毕才可以开始工作,而测试则更是要等到B和A都完成后才开始。一旦B有所改动,牵一发就会牵一发而动全身。这会是一个让人崩溃的事。

这就像流水线,必须等到上一个人完成后,下一个人才可以开始,这是万万不能忍受的。

 

那么有没有更好的办法呢?

答案是肯定有,接下来欢迎:依赖倒置原则正式入场

ICard(汽车类接口):
//汽车类接口
public interface ICard {
    void run();
}
Benz:
public class Benz implements ICard {
    @Override
    public void run() {
        System.out.println("开奔驰咯。。。");
    }
}
BMW:
public class BMW implements ICard {
    @Override
    public void run() {
        System.out.println("宝马启动啦。。。");
    }
}
IDriver:
//司机接口
public interface IDriver {
    void driver(ICard card);
}
DriverImpl:
//IDriver实现类
public class DriverImpl implements IDriver {

    @Override
    public void driver(ICard card) {
        card.run();
    }
}

上车吧,兄弟:

import org.springframework.context.annotation.Bean;

public class Test {
    public static void main(String[] args){
        IDriver driver = new DriverImpl();
        ICard card = new Benz();
        driver.driver(card);
    }
}

这么一看,无论我们后来再添加什么车,只需要重新实现该车的实现类就可以了,对其他没有任何影响。

三、依赖倒置的三种写法:

对象的依赖有三种传递方式:

1、构造函数传递依赖对象

IDriver:

//司机接口
public interface IDriver {
    void driver();
}

DriverImpl:

//IDriver实现类
public class DriverImpl implements IDriver {
    private  ICard card;

    public DriverImpl(ICard card){
        this.card = card;
    }

    @Override
    public void driver() {
        this.card.run();
    }
}

上车试试:

import org.springframework.context.annotation.Bean;

public class Test {
    public static void main(String[] args){
        IDriver driver = new DriverImpl(new BMW());
        driver.driver();
    }
}

2、setter传递依赖对象

IDriver:

//司机接口
public interface IDriver {
    void setter(ICard card);
    void driver();
}
DriverImpl:
//IDriver实现类
public class DriverImpl implements IDriver {
    private  ICard card;
    
    @Override
    public void setter(ICard card) {
        this.card = card;
    }

    @Override
    public void driver() {
        this.card.run();
    }
}

试试:

public class Test {
    public static void main(String[] args){
        IDriver driver = new DriverImpl();
        driver.setter(new Benz());
        driver.driver();
    }
}

3、接口声明依赖对象

第二点采用的就是接口声明依赖对象,该方法也叫接口注入,这里就不再举例子了。

你可能感兴趣的:(JAVA,设计模式,依赖注入,构造函数传递依赖,依赖倒置,setter传递依赖,接口声明依赖)