六大设计原则-依赖倒置原则

 4.依赖倒置原则(Dependence Inversion Principle)(DIP)
高层模块不应该依赖底层模块,二者都依赖其抽象; 抽象不应该依赖细节,细节依赖抽象。面向接口编程。
假设我们现在要组装一台电脑,电脑硬件有cpu和内存,而CPU有Intel和AMD两种类型,内存有DDR3 和DDR4两种,那么我们的传统的设计是这样的:
首先我们写出CPU和内存的实现类:
class AMDCpu{
    void run() {
        System.out.println("AMD CPU在工作");
    }
}
class IntelCpu{
    void run() {
        System.out.println("Intel CPU在工作");
    }
}
class DDR3{
    
    void run() {
        System.out.println("DDR3 内存在工作");
    }
}
class DDR4{
    void run() {
        System.out.println("DDR4 内存在工作");
    }
}
此时,我们要组装一台Intel+DDR3的电脑,那么我们的电脑应该这样写:
class Computer{
    private IntelCpu cpu;
    private DDR3 memory;

    void run() {
        this.cpu.run();
        this.memory.run();
    }

    public IntelCpu getCpu() {
        return cpu;
    }

    public void setCpu(IntelCpu cpu) {
        this.cpu = cpu;
    }

    public DDR3 getMemory() {
        return memory;
    }

    public void setMemory(DDR3 memory) {
        this.memory = memory;
    }
}
public class TraditionDesign {
    public static void main(String[] args) {
        Computer computer = new Computer();
        IntelCpu cpu = new IntelCpu();
        computer.setCpu(cpu);
        DDR3 ddr3 = new DDR3();
        computer.setMemory(ddr3);
        computer.run();
    }
}
现在电脑能运行了,大体看起来没啥问题,但是如果我们此时想要将内存换程DDR4的或者cpu 换成AMD的,那么我们就需要更改Computer类的属性:
class Computer{
    private AMDCpu cpu;
    private DDR4 memory;

    void run() {
        this.cpu.run();
        this.memory.run();
    }

    public AMDCpu getCpu() {
        return cpu;
    }

    public void setCpu(AMDCpu cpu) {
        this.cpu = cpu;
    }

    public DDR4 getMemory() {
        return memory;
    }

    public void setMemory(DDR4 memory) {
        this.memory = memory;
    }
}
public class TraditionDesign {
    public static void main(String[] args) {
        Computer computer = new Computer();
        AMDCpu cpu = new AMDCpu();
        computer.setCpu(cpu);
        DDR4 ddr4 = new DDR4();
        computer.setMemory(ddr4);
        computer.run();
    }
}
可以看到,我们想要个更改电脑的配件,那么类就要重新定义属性类型,相应的getter和setter方法也要更改,那么调用getter和setter方法的客户端也要更改代码,更改的地方越多,风险就越大。
依赖倒置原则的核心是:不要面对实现编程,要面对接口或面对抽象类编程。
那么我们看看如果使用依赖倒置原则我们应该如何实现:
首先定义两个接口:
interface Cpu{
    void run();
}
interface Memory{
    void run();
}
然后实现类实现接口
class AMDCpu implements Cpu{
    @Override
    public void run() {
        System.out.println("AMD CPU在工作");
    }
}
class IntelCpu implements Cpu{
    @Override
    public void run() {
        System.out.println("Intel CPU在工作");
    }
}
class DDR3 implements Memory{

    @Override
    public void run() {
        System.out.println("DDR3 内存在工作");
    }
}
class DDR4 implements Memory{
    @Override
    public void run() {
        System.out.println("DDR4 内存在工作");
    }
}
更改我们的Computer属性为接口或抽象类类型的:
/**
 * 依赖倒置原则
 * @author ZhaoShuai
 * @date Create in 2020/4/9
 **/
public class DependenceInversionPrinciple {

    static class Computer{
        private Cpu cpu;
        private Memory memory;

        void run() {
            this.cpu.run();
            this.memory.run();
        }

        public Cpu getCpu() {
            return cpu;
        }

        public void setCpu(Cpu cpu) {
            this.cpu = cpu;
        }

        public Memory getMemory() {
            return memory;
        }

        public void setMemory(Memory memory) {
            this.memory = memory;
        }
    }

    public static void main(String[] args) {
        Computer computer = new DependenceInversionPrinciple.Computer();
        computer.setCpu(new IntelCpu());
        computer.setMemory(new DDR3());
        computer.run();
    }
}
从上面代码我们可以看出当我们需要组装一台电脑时,我们只需要在客户端设置不同的实现类对象,就可以随意组装电脑而不用更改Computer类。例如我们现在更改为AMD+DDR4:
public static void main(String[] args) {
        Computer computer = new DependenceInversionPrinciple.Computer();
        computer.setCpu(new AMDCpu());
        computer.setMemory(new DDR4());
        computer.run();
    }
我们之更改了客户端的调用,就完成了一台新电脑的组装,对比这两种是实现方式,我们可以发现
依赖倒置原则的好处有:
`1.代码的可扩展性变好了,我们以后可能在新增新的CPU类型,无需改变现有的类,只需要实现Cpu接口,然后再客户端传递新的类型就行了。`
`2.代码的耦合程度变低了,无论我们想要组装什么类型的电脑,都无需更改Computer类,因为类里的Cpu和Memory是接口类型,我们只要传递的是这个接口的实现,无论传递什么值都可以`
所以依赖倒置原则的核心就是:`应该面向接口或抽象类编程`
原文地址:https://www.cnblogs.com/Zs-book1/p/12714111.html