[Design Patterns] 高階和低階之分

因為相依注入 (Dependency Injection) 的日漸盛行,使得相依反轉原則 (Dependency Inversion Principle, DIP) 這個詞被愈用愈多,它的說明是 "將原本相依於低階實作的相依性,轉換為相依至高階抽象",不過這個高階和低階的意義是什麼? 我想要再多闡述一下。

Dependency Inversion Principle 有兩個要求:

A. High level modules should not depend upon low level modules. Both should depend upon abstrations. (高階模組不能相依於低階模組,而兩者都要相依於抽象)
B. Abstractions should not depend upon details. Details should depend upon abstractions. (抽象不可以相依於細節,而細節必須相依於抽象)

由要求中能看得出來抽象 (Abstractions) 的重要性,在物件導向中的抽象有兩種實作方式,一種是利用介面 (Interface),另一種是抽象類別 (Abstract Class),這兩種的差異是:

介面本身並沒有實作,但它有強制要求實作者 (Implementator) 實作介面內所有成員的權力,因此很適合拿來當契約 (Contract),只要有實作指定介面就一定能找到特定的成員。
抽象類別本身可以有實作,但它可以將實作交由子類別實作,本身不提供實作碼,因此適合作為提供協助或事先定義部份流程,再將差異的部份交由子類別實作的設計方式。
通常說抽象化,介面是最多人使用的方法,但不是一定,利用抽象類別來實作的抽象也所在多有。

通常在做系統分析與設計時,當看系統的高度升高時,就能看到各元件的流程,再升高一點,就能看到系統之間的整合方式,再升高一點,就能看到整個系統的架構,因此所謂的高階 (High level),是指以系統分析的高度,將架構內各個具體的細節加以抽象化到較高的位置時,它就是高階物件,而當元件開始擺脫細節的時候,設計者就會抽絲剝繭將共同的特性抽出來,這時設計的位階就會逐步增加,當增加到不能再增加的時候,抽象就形成了。

在抽象的形成過程中,系統分析師基本上會檢視要抽象的成員抽出的程度,據以調整細節設計,因此細節會自然的相依於抽象,這些細節的部份的位階就會較低,因此也被稱為低階 (Low level) 物件,這類物件通常稱為具體類別 (Concrete Class)。

當描述所涵蓋的範圍愈廣,通常它就是愈抽象;當描述的細節愈多,通常它就是愈具體。

用這種方式去擺介面、抽象類別與具體類別時,它的實作方針就出來了:

介面用於最高的抽象層次,因為它具有最高的強制力,如同法規。
抽象類別用於次高的抽象層次,因為它需要因地制宜,如同執行細則。
具體類別用於實作層次。

當抽象與具體實作都分開之後,整個物件的架構圖就很明確了,接下來就要解決兩個問題:

1. 具體相依於抽象,這個問題最好解,因為只要實作特定的介面或抽象類別即可,大多數都是以介面為主。
2. 讓具體與抽象的相依於執行時期生效,這個部份就是相依注入 (Dependendy Injection) 的課題了。