一、什麼是依賴倒轉原則
依賴倒轉原則(Dependency Inversion Principle,DIP)是SOLID原則中的一條,它是指依賴關係中高層模塊不應該依賴於底層模塊,二者都應該依賴於抽象接口。同時,抽象接口不應該依賴於實現細節,實現細節應該依賴於抽象接口。
簡而言之,該原則要求我們針對接口編程,而不是針對實現編程,在設計類之間的依賴關係時,要依賴於抽象而不是具體實現。
// 依賴倒轉原則示例代碼:
// 抽象接口IWorker
interface IWorker {
public void work();
}
// 實現接口IWorker的類WorkerA
class WorkerA implements IWorker {
public void work() {
System.out.println("WorkerA is working.");
}
}
// 實現接口IWorker的類WorkerB
class WorkerB implements IWorker {
public void work() {
System.out.println("WorkerB is working.");
}
}
// HighLevelModule 高層模塊不依賴具體實現(WorkerA、WorkerB),而是依賴於抽象接口IWorker
class HighLevelModule {
private IWorker worker;
public HighLevelModule(IWorker worker) {
this.worker = worker;
}
public void doWork() {
this.worker.work();
}
}
二、依賴倒轉原則的好處
採用依賴倒轉原則設計的代碼更加靈活,能夠降低模塊間的耦合度,提高代碼的可維護性、可擴展性和可復用性。
1. 降低模塊間的耦合度
當採用依賴倒轉原則設計的代碼時,模塊之間的依賴關係會變得鬆散,各模塊之間的耦合度也會減少,這樣就可以方便地對模塊進行替換、修改或刪除,而不會牽一髮而動全身。
2. 提高代碼的可維護性
當依賴關係變得鬆散後,當一個模塊發生變化時,不會影響到其他模塊的正常運行,因此對模塊進行維護時也更加方便。
3. 提高代碼的可擴展性
當需要增加新的功能時,可以通過添加新的實現類,而不需要修改原有的代碼,這樣就能夠方便地擴展功能。
4. 提高代碼的可復用性
由於依賴倒轉原則能夠提高代碼的靈活性、可維護性和可擴展性,因此也能夠提高代碼的可復用性。
5. 降低開發成本
編寫符合依賴倒轉原則的代碼,能夠提高代碼的質量和可維護性,從而減少出現問題的幾率,降低開發成本。
三、如何遵循依賴倒轉原則
1. 抽象接口
為了實現依賴倒轉原則,需要將底層模塊的實現細節封裝在抽象的接口中,並將高層模塊依賴於這個抽象接口。
抽象接口用於描述行為,而不是實現細節,因此抽象接口不應該包含任何具體實現細節。
2. 實現類
實現類是抽象接口的具體實現,它包含了實現細節。當需要增加新的功能時,可以通過添加新的實現類,而不需要修改原有的代碼。
3. 高層模塊
高層模塊不依賴具體實現(如 WorkerA、WorkerB),而是依賴於抽象接口(如 IWorker)。高層模塊應該只關心抽象接口的行為,而不關心具體的實現細節。
// 依賴倒轉原則示例代碼:
// 抽象接口IWorker
interface IWorker {
public void work();
}
// 實現接口IWorker的類WorkerA
class WorkerA implements IWorker {
public void work() {
System.out.println("WorkerA is working.");
}
}
// 實現接口IWorker的類WorkerB
class WorkerB implements IWorker {
public void work() {
System.out.println("WorkerB is working.");
}
}
// HighLevelModule 高層模塊不依賴具體實現(WorkerA、WorkerB),而是依賴於抽象接口IWorker
class HighLevelModule {
private IWorker worker;
public HighLevelModule(IWorker worker) {
this.worker = worker;
}
public void doWork() {
this.worker.work();
}
}
// main 方法
public static void main(String[] args) {
IWorker workerA = new WorkerA();
IWorker workerB = new WorkerB();
HighLevelModule highLevelModuleA = new HighLevelModule(workerA);
highLevelModuleA.doWork(); // 輸出 WorkerA is working.
HighLevelModule highLevelModuleB = new HighLevelModule(workerB);
highLevelModuleB.doWork(); // 輸出 WorkerB is working.
}
四、依賴倒轉原則的實際應用
依賴倒轉原則不僅適用於面向對象的程序設計,還可應用於軟件架構設計、框架設計等方面。
例如,在 Spring 框架中,通過依賴注入(Dependency Injection,DI)的方式,在運行時將依賴對象注入到需要它的對象中,實現依賴倒轉原則。
// Spring 依賴注入示例代碼:
// 抽象接口IWorker
interface IWorker {
public void work();
}
// 實現接口IWorker的類WorkerA
class WorkerA implements IWorker {
public void work() {
System.out.println("WorkerA is working.");
}
}
// 實現接口IWorker的類WorkerB
class WorkerB implements IWorker {
public void work() {
System.out.println("WorkerB is working.");
}
}
// HighLevelModule 高層模塊不依賴具體實現(WorkerA、WorkerB),而是通過依賴注入將實現類注入
class HighLevelModule {
private IWorker worker;
public void setWorker(IWorker worker) {
this.worker = worker;
}
public void doWork() {
this.worker.work();
}
}
// 定義 Bean 配置文件注入依賴
<bean id="workerA" class="com.example.demo.worker.WorkerA" />
<bean id="workerB" class="com.example.demo.worker.WorkerB" />
<bean id="highLevelModuleA" class="com.example.demo.module.HighLevelModule">
<property name="worker" ref="workerA" />
</bean>
<bean id="highLevelModuleB" class="com.example.demo.module.HighLevelModule">
<property name="worker" ref="workerB" />
</bean>
// main 方法
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HighLevelModule highLevelModuleA = (HighLevelModule) context.getBean("highLevelModuleA");
highLevelModuleA.doWork(); // 輸出 WorkerA is working.
HighLevelModule highLevelModuleB = (HighLevelModule) context.getBean("highLevelModuleB");
highLevelModuleB.doWork(); // 輸出 WorkerB is working.
}
原創文章,作者:BEVAK,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/368900.html