zoukankan      html  css  js  c++  java
  • 设计模式七大原则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、继承时遵循里氏替换原则

  • 相关阅读:
    2018
    线程的五大状态
    SQL 列转行与行转列
    python中元组(tuple)的拆包unkacping
    python字典的相关操作总结
    C语言使用typedef进行类型重定义
    C++中namespace的用法理解
    ping: unknown host 解决办法
    go环境变量配置liteide配置
    svn出现Authorization failed
  • 原文地址:https://www.cnblogs.com/xiaomaomao/p/14061205.html
Copyright © 2011-2022 走看看