示例1:司機駕駛汽車
問題場景:司機類直接依賴奔馳車類,新增寶馬車需修改司機類代碼。
// 未遵循DIP
class Benz { public void run() { /*...*/ } }
class Driver { public void drive(Benz benz) { benz.run(); }
}
// 遵循DIP:引入接口ICar
interface ICar { void run(); }
class Benz implements ICar { /*...*/ }
class BMW implements ICar { /*...*/ }
class Driver { public void drive(ICar car) { car.run(); }
}
效果:新增汽車類型(如BMW
)無需修改Driver
類,僅需實現ICar
接口。
示例2:用戶接收消息
問題場景:用戶類直接依賴郵件類,新增微信或短信需修改用戶類。
// 未遵循DIP
class Email { public String getInfo() { /*...*/ } }
class Person { public void receive(Email email) { /*...*/ }
}
// 遵循DIP:引入接口IReceiver
interface IReceiver { String getInfo(); }
class Email implements IReceiver { /*...*/ }
class WeChat implements IReceiver { /*...*/ }
class Person { public void receive(IReceiver receiver) { /*...*/ }
}
效果:新增消息類型(如WeChat
)無需修改Person
類,僅需實現IReceiver
接口。
示例3:購物場景
問題場景:顧客類直接依賴具體商品類(如漢堡、薯條),新增商品需修改顧客類。
// 未遵循DIP
class Hamburger { public void eat() { /*...*/ } }
class Person { public void buy(Hamburger hamburger) { hamburger.eat(); }
}
// 遵循DIP:引入接口IDishes
interface IDishes { void eat(); }
class Hamburger implements IDishes { /*...*/ }
class Chips implements IDishes { /*...*/ }
class Person { public void buy(IDishes dishes) { dishes.eat(); }
}
效果:新增商品類型(如Chips
)無需修改Person
類,僅需實現IDishes
接口。
示例4:通知服務
問題場景:通知服務直接依賴郵件發送類,更換短信服務需修改通知邏輯。
// 未遵循DIP
class EmailService { public void sendEmail(String msg) { /*...*/ } }
class NotificationService { public void send(String msg) { new EmailService().sendEmail(msg); }
}
// 遵循DIP:引入接口MessageSender
interface MessageSender { void sendMessage(String msg); }
class EmailService implements MessageSender { /*...*/ }
class SMSService implements MessageSender { /*...*/ }
class NotificationService { private MessageSender sender; public NotificationService(MessageSender sender) { this.sender = sender; } public void send(String msg) { sender.sendMessage(msg); }
}
效果:通過構造器注入依賴,更換消息服務(如SMSService
)僅需修改調用層。
依賴傳遞的三種方式
- 接口傳遞:通過方法參數傳遞抽象(如
Driver.drive(ICar car)
)。 - 構造器注入:通過構造函數依賴注入(如
NotificationService
依賴MessageSender
)。 - Setter注入:通過Setter方法動態注入依賴(如
public void setSender(MessageSender sender)
)。
DIP的核心優勢
- 降低耦合性:模塊間通過抽象交互,減少直接依賴。
- 提高擴展性:新增功能只需添加實現類,無需修改高層邏輯(符合開閉原則)。
- 支持并行開發:接口定義后,高低層模塊可獨立開發與測試(如TDD模式)。
- 增強可維護性:變更影響范圍受限于低層模塊,減少風險。
總結
依賴倒置原則通過抽象(接口/抽象類)實現模塊解耦,核心實踐包括:
- 定義清晰的接口或抽象類作為模塊間的契約。
- 使用依賴注入(構造器、Setter等)傳遞具體實現。
- 高層模塊僅依賴抽象,低層模塊實現抽象。
結合Spring框架的DI容器,可進一步自動化依賴管理,提升代碼復用性和靈活性。