因為相依注入 (Dependency Injection) 的日漸盛行,使得相依反轉原則 (Dependency Inversion Principle, DIP) 這個詞被愈用愈多,它的說明是 "將原本相依於低階實作的相依性,轉換為相依至高階抽象",不過這個高階和低階的意義是什麼? 我想要再多闡述一下。
Dependency Inversion Principle 有兩個要求:
B. Abstractions should not depend upon details. Details should depend upon abstractions. (抽象不可以相依於細節,而細節必須相依於抽象)
由要求中能看得出來抽象 (Abstractions) 的重要性,在物件導向中的抽象有兩種實作方式,一種是利用介面 (Interface),另一種是抽象類別 (Abstract Class),這兩種的差異是:
抽象類別本身可以有實作,但它可以將實作交由子類別實作,本身不提供實作碼,因此適合作為提供協助或事先定義部份流程,再將差異的部份交由子類別實作的設計方式。
通常在做系統分析與設計時,當看系統的高度升高時,就能看到各元件的流程,再升高一點,就能看到系統之間的整合方式,再升高一點,就能看到整個系統的架構,因此所謂的高階 (High level),是指以系統分析的高度,將架構內各個具體的細節加以抽象化到較高的位置時,它就是高階物件,而當元件開始擺脫細節的時候,設計者就會抽絲剝繭將共同的特性抽出來,這時設計的位階就會逐步增加,當增加到不能再增加的時候,抽象就形成了。
在抽象的形成過程中,系統分析師基本上會檢視要抽象的成員抽出的程度,據以調整細節設計,因此細節會自然的相依於抽象,這些細節的部份的位階就會較低,因此也被稱為低階 (Low level) 物件,這類物件通常稱為具體類別 (Concrete Class)。
用這種方式去擺介面、抽象類別與具體類別時,它的實作方針就出來了:
抽象類別用於次高的抽象層次,因為它需要因地制宜,如同執行細則。
具體類別用於實作層次。
當抽象與具體實作都分開之後,整個物件的架構圖就很明確了,接下來就要解決兩個問題:
1. 具體相依於抽象,這個問題最好解,因為只要實作特定的介面或抽象類別即可,大多數都是以介面為主。
2. 讓具體與抽象的相依於執行時期生效,這個部份就是相依注入 (Dependendy Injection) 的課題了。