设计模式七大原则03---依赖倒转原则

一、依赖倒转原则(Dependence Inversion Principle)特点

1、依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多.以抽象为基础搭建的架构比以细节为基础的架构要稳定的多.在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类

2、高层模块不应该依赖低层模块,二者都应该依赖其抽象

3、抽象不应该依赖细节,细节应该依赖抽象

4、使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成

5、依赖倒转(倒置)的中心思想是面向接口编程

 

二、案例演示

完成 Person 接收消息的功能

方式一、普通实现

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Person person = new Person();
        person.receiveMessage(new Email());
    }
}

class Person{
    public void receiveMessage(Email email){
        email.receive();
    }
}

class Email {
    public void receive(){
        System.out.println("接收 email 信息");
    }
}

上面的代码已经完成了我们的需求,但是存在一个问题,我们 Person 类里面的 receiveMessage(Email email) 方法参数类型是 Email 类型的,它代表的意思是只能接收 Email 类型的消息,如果我这个时候想接收微信消息、QQ 消息,那么就要继续重写 receiveMessage() 方法,这样就比较麻烦.所以我们需要使用依赖倒置来改进

方式二、依赖倒置

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Person person = new Person();
        person.receiveMessage(new Email());
        person.receiveMessage(new Wechat());
        person.receiveMessage(new QQ());
    }
}

interface Message {
    public abstract void receive();
}

class Person {
    public void receiveMessage(Message message) {
        message.receive();
    }
}

class Email implements Message {
    public void receive() {
        System.out.println("接收 email 信息");
    }
}

class Wechat implements Message {
    public void receive() {
        System.out.println("接收 wechat 信息");
    }
}

class QQ implements Message {
    public void receive() {
        System.out.println("接收 qq 信息");
    }
}

使用依赖倒置改进之后,扩展起来也比较方便了.

 

三、依赖关系传递的三种方式

依赖是可以传递的,A对象依赖B对象,B对象又依赖C对象,C对象又依赖D对象......生生不息,依赖不止.要记住一点:只要做到抽象依赖,即使多层的依赖传递也无所畏惧.对象的依赖关系主要有三种方式来传递.

1、接口传递

在接口的方法中声明依赖对象,该方法也叫做接口注入.

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Idriver idriver = new Driver();
        idriver.drive(new Benz());
        idriver.drive(new Porsche());
    }
}

interface Icar {
    public void run();
}

interface Idriver {
    public void drive(Icar icar);
}

class Benz implements Icar {
    @Override
    public void run() {
        System.out.println("Benz run...");
    }
}

class Porsche implements Icar {
    @Override
    public void run() {
        System.out.println("Porsche run...");
    }
}

class Driver implements Idriver {
    @Override
    public void drive(Icar icar) {
        icar.run();
    }
}

2、构造方法传递

在类中通过构造函数依赖对象,安装依赖注入的说法,这种方式叫做构造函数注入.

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Idriver benz = new Driver(new Benz());
        benz.drive();
        Idriver porsche = new Driver(new Porsche());
        porsche.drive();
    }
}

interface Icar {
    public void run();
}

interface Idriver {
    public void drive();
}

class Benz implements Icar {
    @Override
    public void run() {
        System.out.println("Benz run...");
    }
}

class Porsche implements Icar {
    @Override
    public void run() {
        System.out.println("Porsche run...");
    }
}

class Driver implements Idriver {
    private Icar icar;

    public Driver(Icar icar){
        this.icar = icar;
    }

    @Override
    public void drive() {
        icar.run();
    }
}

3、setter 方法传递

在抽象中设置 setter 方法声明依赖关系,依照依赖注入的说法.这个是 setter 依赖注入

public class DesignPatternPrinciple {
    public static void main(String[] args) {
        Driver benzDriver = new Driver();
        benzDriver.setIcar(new Benz());
        benzDriver.drive();

        Driver PorsDriver = new Driver();
        PorsDriver.setIcar(new Porsche());
        PorsDriver.drive();
    }
}

interface Icar {
    public void run();
}

interface Idriver {
    public void drive();
}

class Benz implements Icar {
    @Override
    public void run() {
        System.out.println("Benz run...");
    }
}

class Porsche implements Icar {
    @Override
    public void run() {
        System.out.println("Porsche run...");
    }
}

class Driver implements Idriver {
    private Icar icar;

    public void setIcar(Icar icar) {
        this.icar = icar;
    }

    @Override
    public void drive() {
        icar.run();
    }
}

  

四、依赖倒置注意事项

1、低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好

2、变量的声明类型尽量是抽象类或接口,,这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化

3、继承时遵循里氏替换原则

 

posted @ 2020-11-30 14:35  变体精灵  阅读(152)  评论(0编辑  收藏  举报