依賴倒置原則(Dependence Inversion Principle)


背景

這幾天組內的人一起學習DDD,里面再次提到了依賴倒置原則,在這學習過程中,大家又討論了一下依賴倒置原則。

說明

采用依賴倒置原則可以減少類間的耦合性,提高系統的穩定性,減少並行開發引起的風險,提高代碼的可讀性和可維護性。

那么依賴倒置原則是什么呢?

高層次的模塊不應該依賴於低層次的模塊,他們都應該依賴於抽象。

抽象不應該依賴於具體,具體應該依賴於抽象。

High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend on details. Details should depend on abstractions.

依賴倒置原則是Robert C. Martin在1996年為“C++Reporter”所寫的專欄Engineering Notebook的第三篇,后來加入到他在2002年出版的經典著作“Agile Software Development, Principles,Parrerns,and Practices”一書中。

例子

下面是一個違反依賴倒置原則的示例。我們有高層類Manager,還有底層類Worker。現在我們需要在應用程序中增加一個新模塊,以模擬由雇用新專業工人決定的公司結構變化,我們為此創建了一個新的類SuperWorker

讓我們假設Manager類相當復雜,包含非常復雜的邏輯。現在我們必須改變它,以引入新的SuperWorker。讓我們看看缺點:

  • 我們必須更改類Manager(記住這是一個復雜的類,這將涉及時間和精力進行更改)。
  • Manager類中的某些功能可能會受到影響。
  • 單元測試應重做。

所有這些問題都可能需要很多時間來解決,並且它們可能會在舊功能中誘發新的錯誤。如果應用程序是按照依賴倒置原則來設計的,情況就不一樣了。這意味着我們設計Manager類時,IWorker 接口和實現 IWorker 接口的Worker類即可。當我們需要添加SuperWorker時,我們要做的就是為此實現IWorker接口。現有類沒有其他更改。

// Dependency Inversion Principle - Bad example
class Worker {
	public void work() {
		// ....working
	}
}

class Manager {
	Worker worker;

	public void setWorker(Worker w) {
		worker = w;
	}

	public void manage() {
		worker.work();
	}
}

class SuperWorker {
	public void work() {
		//.... working much more
	}
}

以下是支持依賴性反轉原則的代碼。在這個新設計中,通過IWorker 界面添加了一個新的抽象層。現在,上述代碼中的問題已經解決(考慮到高層邏輯沒有變化):

  • 在添加SuperWorker時,Manager類不需要更改。
  • 由於我們不會改變它,因此最大限度地降低影響Manager器類中當前舊功能的風險。
  • 無需重做Manager類的單元測試。
// Dependency Inversion Principle - Good example
interface IWorker {
    public void work();
}

class Worker implements IWorker{
    public void work() {
        // ....working
    }
}

class SuperWorker  implements IWorker{
    public void work() {
        //.... working much more
    }
}

class Manager {
    IWorker worker;

    public void setWorker(IWorker w) {
        worker = w;
    }

    public void manage() {
        worker.work();
    }
}

當然,使用此原則意味着加大努力,將導致更多的類和接口來維護,換句話說,在更復雜的代碼,但更靈活。不應盲目地將這一原則應用於每個類或每個模塊。如果我們的類功能將來更有可能保持不變,則無需應用此原則。

“倒置”的解釋

《設計模式之禪》中對“倒置”的解釋:

講了這么多,估計大家對“倒置”這個詞還是有點不理解,那到底什么是“倒置”呢?我們先說“正置”是什么意思,依賴正置就是類間的依賴是實實在在的實現類間的依賴,也就是面向實現編程,這也是正常人的思維方式,我要開奔馳車就依賴奔馳車,我要使用筆記本電腦就直接依賴筆記本電腦,而編寫程序需要的是對現實世界的事物進行抽象,抽象的結果就是有了抽象類和接口,然后我們根據系統設計的需要產生了抽象間的依賴,代替了人們傳統思維中的事物間的依賴,“倒置”就是從這里產生。

可以這么解釋:高層A依賴於低層B修改為高層A依賴於抽象層C,低層B依賴於抽象層C,而抽象層C是低層B的高層,所以說低層依賴於高層了,即倒置。但是A依賴於C,這個不能說是低層依賴於高層吧,A和C誰高誰低是這么判定的?因為抽象層C是屬於A層的,即由A層來規定抽象層C的接口規范,而B是對C的實現,因此通過引入C層實現了“依賴倒置”。

總結

一句話:依賴倒置原則的核心就是面向抽象(抽象類或者接口)編程。

設計類結構的方法是從高層模塊到底層模塊:
高層類 --> 抽象層 --> 底層類

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM