1. 核心概念
依赖倒置原则(Dependency Inversion Principle, DIP) 是SOLID原则中的"D",包含两个关键点:
- 高层模块不应依赖低层模块,二者都应依赖抽象
- 抽象不应依赖细节,细节应依赖抽象
2. 使用场景
典型应用场景
- 系统需要支持多种实现方式
- 模块间需要解耦
- 需要进行单元测试(依赖mock对象)
- 系统可能面临实现方式的变更
反模式示例
class LightBulb: # 低层模块def turn_on(self):print("Bulb turned on")def turn_off(self):print("Bulb turned off")class Switch: # 高层模块def __init__(self):self.bulb = LightBulb() # 直接依赖具体实现def operate(self):self.bulb.turn_on()
3. 最佳实践
正确实现方式
from abc import ABC, abstractmethod# 抽象接口
class Switchable(ABC):@abstractmethoddef turn_on(self):pass@abstractmethoddef turn_off(self):pass# 低层模块实现接口
class LightBulb(Switchable):def turn_on(self):print("LED bulb turned on")def turn_off(self):print("LED bulb turned off")class Fan(Switchable):def turn_on(self):print("Fan started spinning")def turn_off(self):print("Fan stopped")# 高层模块依赖抽象
class Switch:def __init__(self, device: Switchable): # 依赖抽象self.device = devicedef operate(self):self.device.turn_on()# 使用示例
bulb = LightBulb()
switch = Switch(bulb)
switch.operate()fan = Fan()
fan_switch = Switch(fan)
fan_switch.operate()
关键优点
- 可扩展性:轻松添加新设备类型
- 可测试性:可以创建测试用的mock对象
- 低耦合:Switch类不依赖具体设备实现
- 可维护性:设备实现变化不会影响Switch类
4. Python特有实现方式
使用协议(Protocol)实现
Python 3.8+ 可以使用更灵活的协议实现:
from typing import Protocolclass Switchable(Protocol):def turn_on(self) -> None: ...def turn_off(self) -> None: ...class SmartTV:# 不需要显式继承,只需要实现协议方法def turn_on(self):print("TV powered on")def turn_off(self):print("TV powered off")# 同样可以工作
tv = SmartTV()
tv_switch = Switch(tv)
tv_switch.operate()
5. 实际应用建议
- 适度使用:简单场景不必过度设计
- 结合DI容器:在大型项目中可使用依赖注入框架
- 接口设计:保持抽象接口小而专注(ISP原则)
- 文档说明:对抽象接口进行充分文档说明
6. 常见误区
❌ 为每个类都创建接口
✅ 只为确实需要多实现的模块创建抽象
❌ 抽象接口包含太多方法
✅ 遵循接口隔离原则(ISP)
❌ 认为DIP就是依赖注入(DI)
✅ DI是实现DIP的一种技术手段