5-软件设计原则详解-依赖倒置原则

5-软件设计原则详解-依赖倒置原则

1. 依赖倒置原则 (Dependency Inversion Principle, DIP)

1. 定义

  1. 高层模块不应该依赖于低层模块,两者都应该依赖于抽象
  2. 抽象不应该依赖于细节,细节应该依赖于抽象

2. 解释

  • 通过抽象(接口或抽象类)进行解耦
  • 使用依赖注入等技术实现
  • 提高代码的可测试性和灵活性

3. 关键点

  • 传统的依赖关系(如分层架构中)是自上而下的,高层模块直接调用低层模块,导致紧耦合。
  • DIP通过引入抽象(接口或抽象类)将依赖关系“倒置”,使高层和低层模块都依赖抽象,而非具体实现。

4. 什么是“倒置”?

传统依赖关系(未倒置)

  • 高层模块直接依赖低层模块

    高层模块 → 低层模块
    

    问题:低层模块的改动会直接影响高层模块(例如修改数据库访问代码会导致业务逻辑变动)。

倒置后的依赖关系

  • 高层和低层模块均依赖抽象

    高层模块 → 抽象 ← 低层模块
    

    效果

    • 高层模块不再直接依赖低层模块,而是通过抽象间接调用。
    • 低层模块需要实现抽象接口,从而“依赖”抽象。
    • 依赖方向从“自上而下”变为“双向依赖抽象”,这就是“倒置”的含义。

5. 高层模块 vs 低层模块

高层模块(High-Level Module)

  • 定义:包含核心业务逻辑、应用策略的模块,通常解决复杂问题。
  • 特点
    • 关注“做什么”(What),而非“如何做”(How)。
    • 例如:订单处理系统、支付流程控制器。
  • 传统误区:高层模块直接调用低层模块的具体实现(如*Impl类)。

低层模块(Low-Level Module)

  • 定义:实现具体技术细节的模块,通常是一些基础服务或工具。
  • 特点
    • 关注“如何做”(How),例如数据库访问、文件IO、网络通信。
    • 例如:MySQL数据库操作、Redis缓存实现。
  • 传统误区:低层模块的设计直接影响高层模块。

6. 实际应用场景

  • 插件式架构:通过抽象允许动态扩展功能(如IDE的插件系统)。
  • 单元测试:高层模块通过抽象接口可轻松Mock低层模块。
  • 框架设计:框架定义抽象接口,用户提供具体实现(如Spring的DataSource)。

通过DIP,系统的核心逻辑(高层模块)不再受技术细节(低层模块)的束缚,从而更易于扩展和维护。

示例

// 违反DIP
class LightBulb {
    public void turnOn() { /* ... */ }
    public void turnOff() { /* ... */ }
}

class Switch {
    private LightBulb bulb;
    
    public Switch(LightBulb bulb) {
        this.bulb = bulb;
    }
    
    public void operate() {
        // 直接依赖具体实现
        bulb.turnOn();
    }
}

// 遵循DIP
interface Switchable {
    void turnOn();
    void turnOff();
}

class LightBulb implements Switchable {
    public void turnOn() { /* ... */ }
    public void turnOff() { /* ... */ }
}

class Fan implements Switchable {
    public void turnOn() { /* ... */ }
    public void turnOff() { /* ... */ }
}

class Switch {
    private Switchable device;
    
    public Switch(Switchable device) {
        this.device = device;
    }
    
    public void operate() {
        device.turnOn();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值