设计模式原则---依赖倒转原则
- 依赖倒转原则
- 一 官方定义
- 基本介绍
- 二 案例演示
- 普通方式实现
- **解决方案**
- **案例分析**
- **案例总结**
- 依赖倒转原则方式实现
- **解决方案**
- 案例分析
- **案例总结**
- 注意事项&细节
- 三 依赖关系传递方式
- 一、通过接口传递
- 二、通过构造方法传递
- 三、通过set()方法传递
依赖倒转原则
其实我们在实际的开发中大部分都是遵守依赖倒转原则。即面向接口编程,习惯成自然,不知所以然。通过这个分析明确出来,以后写代码时就明白了为什么这样写,同时就会有意的去遵守这些看似简单但却很重要的设计模式原则,降低耦合提高代码质量。
一 官方定义
- 依赖倒转原则,又称依赖倒置原则(Dependence Inversion Principle),又称DIP原则,官方定义为:
High level modules should not depend upon low level modules. Both should depend upon abstractions.
(上层模块不应该依赖底层模块,它们都应该依赖于抽象)
Abstractions should not depend upon details. Details should depend upon abstractions.
(抽象不应该依赖于细节,细节应该依赖于抽象)
基本介绍
何为抽象? —> 接口或者抽象类
何为细节?—> 实现类
换句话说 依赖倒转原则核心的理念 相对于细节来说,抽象要稳定得多
要求我们 面向接口编程
java中抽象类和接口的目的就是制定好规范,不会涉及具体的操作 展现细节或者实现具体的业务逻辑,这些是要交给对应的实现类来解决的、换句话说抽象类和接口的价值就在于设计
总结: 依赖倒转原则其实就是要求我们面向接口编程,其实就是要求我们在编码的时候注意抽象类和接口的设计
二 案例演示
假设有这样一个场景 现在有一个工作人员,收发钉钉消息和微信消息,qq消息
普通方式实现
解决方案
案例分析
现在work接收的是钉钉消息,哪天比较忙接收微信,或者qq消息等等。那我们需要扩展功能的,那根据这样的实现逻辑就需要
- 增加微信类并添加发送消息方法;
- 增加qql类添加发送消息方法;
- 在work类中新定义两个新的方法来接收微信和qq消息
案例总结
由传统案例看出我们不光需要新增类,work类中也需要新增相应的接收方法才可以,这显然比较笨重,维护性差的同时频繁修改代码也会带来意向不到的风险。
如果按照依赖倒转原则思想,使用接口为编程,对案例进行重构来看看什么效果。
依赖倒转原则方式实现
为了解决上述案例的弊端我们引入依赖倒转原则方式
解决方案
引入接口制定规范:定义 IMessage接口 来表示信息的接收者,钉钉,微信,qq都是消息接收的途径,就可以让他们实现该接口来完成具体的实现细节,然后work只需要与该接口发生关系即可。使用依赖倒转原则进行改造。
public class InversionDemo {
public static void main(String[] args) {
new Worker().getMessage(new WeChat());
new Worker().getMessage(new Message());
new Worker().getMessage(new DingDing());
}
}
//案例演示 - 依赖倒转原则
//假设有这样一个场景 现在有一个工作人员,收发钉钉消息
//引入接口,制定消息的规范
interface IMessage {
void SendMessage();
}
class Worker {
//公共的接收消息方法
public void getMessage(IMessage iMessage) {
iMessage.SendMessage();
}
}
//钉钉类
class DingDing implements IMessage {
@Override
public void SendMessage() {
System.out.println("钉钉上,老板找你加班啦");
}
}
//微信类
class WeChat implements IMessage {
@Override
public void SendMessage() {
System.out.println("钉钉不会,老板给你打微信电话了");
}
}
//qq类
class Message implements IMessage {
@Override
public void SendMessage() {
//TODO...
}
}
案例分析
定义一个接口为模板,让各种消息接收的途径去实现。这样的话如果说业务不光要求这三个,还有第四个第五个接收消息的方式,我们添加对应的实体类,实现接口就可以。work端是不需要变动和维护的。
案例总结
依赖倒转原则本质上 就是通过抽象(抽象类和接口)使得各个类或者模块实现彼此独立,互相不 影响,实现模块间松耦合,要先顶层再细节的方式来进行代码设计
其实我们在实际的开发中大部分都是面向接口编程,习惯成自然,不知所以然。通过这个分析明确出来,以后写代码时就明白了为什么这样写,同时就会有意的去遵守这些看似简单但却很重要的设计模式原则,降低耦合提高代码质量。
注意事项&细节
- 低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好
- 变量的声明类型尽量是抽象类或者接口,这样我们的变量引用和实际对象间,就存在一个缓冲层, 利于程序扩展和优化
- 继承时遵循里式替换原则
三 依赖关系传递方式
一、通过接口传递
interface IMessage{
void sendMessage(Produce produce);
}
//消息真正的生产者
interface Produce{
void produceMessage();
}
class Worker implements IMessage{
@Override
public void sendMessage(Produce produce) {
produce.produceMessage();
}
}
二、通过构造方法传递
//通过构造器来传递
interface IMessage{
void sendMessage();
}
//消息真正的生产者
interface Produce{
void produceMessage();
}
class Worker implements IMessage{
public Produce produce;
public Worker(Produce produce){
this.produce = produce;
}
@Override
public void sendMessage() {
this.produce.produceMessage();
}
}
三、通过set()方法传递
//通过set()方法
interface IMessage{
void sendMessage();
}
//消息真正的生产者
interface Produce{
void produceMessage();
}
class Worker implements IMessage{
public Produce produce;
public void setProduce(Produce produce){
this.produce = produce;
}
@Override
public void sendMessage() {
this.produce.produceMessage();
}
}