设计模式-设计原则-依赖倒置

依赖倒置原则

概念

​ “ 面向接口编程

  • 依赖倒转原则是基于这样的设计理念:

  • 相对于细节的多变性,抽象的东西要稳定的多。

  • 抽象为基础搭建的架构比以细节为基础的架构要稳定的多。

  • 在java中,抽象指的是接口或抽象类细节就是具体的实现类

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


特点

  1. 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  2. 抽象不应该依赖细节
  3. 细节应该依赖抽象 (接口 或 抽象类)
  4. 依赖倒转(倒置)的中心思想是面向接口编程

场景介绍

Person类中 存在一个 接受消息(可能是任意消息)方法 (怎样实现?)

违反–依赖倒置原则

在该例中:

Person具体依赖于Email实现类

如果此时Person还需要接收类似 微信 QQ发送的消息就意味着要多个接收方法的实现

public class Inversion {
    //客户端
    public static void main(String[] args) {
        Person person = new Person();
        person.receiveEmail(new Email("发送了一条消息:Hello World!"));
        person.receiveWeChat(new WeChat("发送了一条消息:Hello World!"));
        person.receiveTencent(new Tencent("发送了一条消息:Hello World!"));
    }
}
//Person类  接受消息功能
//方式 1 依赖具体实现类
class Person{
    public void receiveEmail(Email email){
        System.out.println(email.getInfo());
    }

    public void receiveWeChat(WeChat wechat){
        System.out.println(wechat.getInfo());
    }
    public void receiveTencent(Tencent tencent){
        System.out.println(tencent.getInfo());
    }
}

//邮件类
class Email{
    String info;

    Email(String info){
        this.info = "Email"+info;
    }

    //获取邮件信息
    public String getInfo(){
        return this.info;
    }
}

//微信类
class WeChat{
    String info;

    WeChat(String info){
        this.info = "Wechat"+info;
    }

    //获取微信信息
    public String getInfo(){
        return this.info;
    }
}

//QQ类
class Tencent {
    String info;

    Tencent(String info){
        this.info = "QQ"+info;
    }

    //获取微信信息
    public String getInfo(){
        return this.info;
    }
}

运行结果

在这里插入图片描述

虽然实现了功能

但是导致重复工作(多个功能类似的方法 receive Email、WeChat、Tencent等)不易维护


遵循–依赖倒置原则

优化方法:

引入一个IReceiver接口

Person类与这个接口发生依赖

具体发送消息类(实现类)这只需依赖该 实现该接口即可

public class Inversion {
    //客户端
    public static void main(String[] args) {
        Person person = new Person();
        person.receive(new Email("发送了一条消息:Hello World!"));
        person.receive(new WeChat("发送了一条消息:Hello World!"));
        person.receive(new Tencent("发送了一条消息:Hello World!"));
    }
}
//Person类  接受消息功能
//方式 1 依赖具体实现类
class Person{
    //Person类只需一个方法即可接受所有类型消息
    public void receive(IReceiver receiver){
        System.out.println(receiver.getInfo());
    }
}

//抽象公共接口
interface IReceiver{
    public String getInfo();
}

//邮件类
class Email implements IReceiver{
    String info;

    Email(String info){
        this.info = "Email"+info;
    }

    //获取邮件信息
    @Override
    public String getInfo(){
        return this.info;
    }
}

//微信类
class WeChat implements IReceiver{
    String info;

    WeChat(String info){
        this.info = "Wechat"+info;
    }

    //获取微信信息
    @Override
    public String getInfo(){
        return this.info;
    }
}
//QQ类
class Tencent implements IReceiver{
    String info;

    Tencent(String info){
        this.info = "QQ"+info;
    }

    //获取微信信息
    @Override
    public String getInfo(){
        return this.info;
    }
}

运行结果

在这里插入图片描述

在优化后:

Person类需要一个receive方法即可接收所有类型的消息

在后期维护中 若某个消息功能不再使用 也只需要删除对应的实现类不用修改Person类


依赖方法的传递方式

  1. 接口传递
  2. 构造方式传递
  3. setter方法传递

构造方式传递

–:即 Person通过构造方法直接传入实现类 方法内部具体通过传入的实现类直接实现

public static void main(String[] args) {
       Person personE = new Person(new Email("发送了一条消息:Hello World!"));
       personE.receive();

       Person personW = new Person(new WeChat("发送了一条消息:Hello World!"));
       personW.receive();

       Person personT = new Person(new Tencent("发送了一条消息:Hello World!"));
       personT.receive();
   }
}
//Person类  接受消息功能
//方式 1 依赖具体实现类
class Person{
	//抽象公共接口对象
   IReceiver receiver;
   
   public Person(IReceiver receiver){
       this.receiver = receiver;
   }

	//通过传入的实现类  直接使用
   public void receive(){
       System.out.println(this.receiver.getInfo());
   }
}

//抽象公共接口
interface IReceiver{
   public String getInfo();
}

//邮件类
class Email implements IReceiver{
	...
}

//微信类
class WeChat implements IReceiver{
	...
}
//QQ类
class Tencent implements IReceiver{
	...
}

可以看到 方法不再需要传递实现类 但是Person对象却在增多

setter方法传递

public static void main(String[] args) {

   Person person = new Person();

   person.setReceiver(new Email("发送了一条消息:Hello World!"));
   person.receive();

   person.setReceiver(new WeChat("发送了一条消息:Hello World!"));
   person.receive();

   person.setReceiver(new Tencent("发送了一条消息:Hello World!"));
   person.receive();
}

//Person类  接受消息功能
//方式 1 依赖具体实现类
class Person{
   
	//抽象公共接口对象
   IReceiver receiver;

   //传入具体实现类对象
   public void setReceiver(IReceiver receiver) {
       this.receiver = receiver;
   }

   public void receive(){
       System.out.println(this.receiver.getInfo());
   }
}

//抽象公共接口
interface IReceiver{
   public String getInfo();
}

//邮件类
class Email implements IReceiver{
	...
}

//微信类
class WeChat implements IReceiver{
	...
}
//QQ类
class Tencent implements IReceiver{
	...
}

因为是非构造方式传递 所以只需一个person即可

但是每次接受不同消息时 必须每次通过setter方法重设实现对象(不设置会产生错误甚至报错)


注意事项及细节

  • 低层模块 尽量都要有抽象类或接口 程序稳定性好 (尽量每个实现类上都有一个抽象接口或抽象类)
  • 变量的声明类型尽量是抽象类或接口,这样变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化
  • 继承时遵循里氏替换原则

在这里插入图片描述

OBJ业务类直接依赖B接口/抽象类缓冲 具体实现类A依赖B接口/抽象类

在后期更改业务时 只需在B类缓冲层中 添加新的方法 即可所有实现类都可以实现升级扩展

本文章用来记录自己学习过程–来源:尚硅谷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值