syshlang设计模式七大原则之依赖倒转原则 (Dependence Inversion Principle) | 浪迹一生

所谓拥有,皆非束缚;所有过往,皆为序章。

0%

设计模式七大原则之依赖倒转原则 (Dependence Inversion Principle)

    依赖倒转原则(DIP: Dependence Inversion Principle)也说依赖倒置原则,包含三层含义:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。依赖倒转(倒置)的中心思想就是面向接口编程。

举个我们日常通信的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author sunys
*/
public class Dependenceinversion {
public static void main(String[] args) {
People people = new People();
people.sendMessageBySMS(new SMScommunicate());
}

private static class SMScommunicate{
public void sendMessage(){
System.out.println("使用手机短信发送信息!");
}
}

private static class People{
public void sendMessageBySMS(SMScommunicate smScommunicate){
smScommunicate.sendMessage();
}
}
}

在很久之前,互联不发达时,我们通信一般采用手机发送短信或者打电话,如上面的代码,一切正常。但是,随机互联网的普及更多的通信方式出现了,例如微信、QQ等,需求场景发生变化,那么最简单的做法就是新增微信和QQ的通讯类,并且给People增加相应的方法。显然,这种方法不能满足多变性需求,且不稳定。所以,我们使用另一种思路解决,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* @author sunys
*/
public class Dependenceinversion1 {
public static void main(String[] args) {
People people = new People();
people.sendMessage(new SMScommunicate());
people.sendMessage(new QQcommunicate());
people.sendMessage(new Wechatcommunicate());
}

private interface Communicate{
void sendMessage();
}

private static class SMScommunicate implements Communicate{
public void sendMessage(){
System.out.println("使用手机短信发送信息!");
}
}

private static class QQcommunicate implements Communicate{

public void sendMessage() {
System.out.println("使用QQ发送信息!");
}
}
private static class Wechatcommunicate implements Communicate{

public void sendMessage() {
System.out.println("使用微信发送信息!");
}
}

private static class People{
public void sendMessage(Communicate communicate){
communicate.sendMessage();
}
}
}

根据依赖倒置原则,在新的解决方案中,我们引入了一个通讯工具的接口Communicate,让几种不同的通信方式去实现接口,这样修改后,无论以后怎样扩展,都不需要再修改People类了。

依赖关系传递的三种方式

  • 接口声明依赖

    在上面日常通信的例子中,我们在用的就是接口声明依赖的方式,该方法也叫做接口注入。

  • 构造函数传递依赖对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
    * 构造函数传递依赖对象
    * @author sunys
    */
    public class People implements Communicate{
    private Communicate communicate;
    //构造函数注入
    public People(Communicate communicate) {
    this.communicate = communicate;
    }
    public void sendMessage() {
    communicate.sendMessage();
    }
    }
    interface Communicate{
    void sendMessage();
    }
  • Setter方法传递依赖对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /**
    * Setter方法传递依赖对象
    * @author sunys
    */
    public class People1 implements Communicate1{
    private Communicate communicate;
    //Setter依赖注入

    public void setCommunicate(Communicate communicate) {
    this.communicate = communicate;
    }

    public void sendMessage() {
    communicate.sendMessage();
    }
    }
    interface Communicate1{
    void sendMessage();
    }

    在java中,抽象指的是接口或抽象类,细节就是具体的实现类,相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。在实际的开发中,低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好;变量的声明类型尽量是抽象类或接口,这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化;使用继承时遵循 里氏代换原则(Liskov Substitution Principle)

------------- The End -------------
  • 本文作者: 浪迹一生
  • 本文链接: https://www.syshlang.com/fa1508aa/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!