定義:
能夠被分解為子任務組,其中每個子任務處於一個特定的抽象層次上。
範例:
網路協議(iso 7層)。
與採用單一模組來相比,分層方法是另一個更好的設計方式,優點有
1.幫助團隊開發,支持增量編碼和測試。
2.使用半獨立元件讓後期的元件交換更容易。
3.更好的實現技術可以透過簡單的重寫代碼分別加入。
環境:
一個需要分解的大系統。
問題:
系統的明顯特色是混合低層與高層的問題且高層依賴低層操作。
系統的一部份處理低層問題,如硬體(傳感器輸入,從文件中讀取或線路讀取電子信號)。另一部份處理高層問題如,使用者介面。
層之間的通信有兩個方向,一個為從高層到低層的請求,另一個為低層到高層的通知,通知可以是對請求的應答或事件的輸入數據。
系統往往需要一些與其垂直相交的水平層。這些操作處在同一個抽象層,但彼此之間很大的部份是獨立的。
關注點:
1.後期代碼的改動應該不影響整個系統。應該被限制在一個元件內且不影響其他元件。
2.介面應該是穩定的,甚至可以用標準來限定。
3.系統各個元件應該可以被替換。元件可以被別的實現方法來替代且不影響系統其他部份。
4.之後可能會建立其他系統,這些系統具有和目前設計一樣的底層問題。
5.相似職責應該分組以提高可理解性和可維護性。每個元件應該是具有內聚力的。
解決方案:
將系統分為適當層次,從最底層(第1層)開始,按照適當順序放置,將抽象層j放在j-1層的上層,直到最高層(第n層)。
不需要說明某層j是不是需要分解為更複雜的子系統。重要的是在某層中所有用到的元件必須工作在同一層
結構:
Layer主要特徵為第j層的服務只被j+1層使用。每個獨立層都要防止被較高層直接訪問。
動態特性:
1.從上往下:客戶向 層n 發出請求,層n 無法完成該請求,於是調用層 n-1 相應的子任務,直到第1層,第1層完成後向上層反饋回去直到層n,從上而下通常稱為請求。
2.從下往上:一個驅動設備(第1層)探測到輸入之後,把輸入轉換成內部格式並報告給第2層。
由下而上通常稱為通知。
3.描述請求只達到某層的範圍,如果層n-1 可以達到需求,一個來自於頂層(層n)的請求可能只需
達到相鄰層即可。
4.彼此能互相通信的層n,a層n 和b層n 彼此是獨立的2個層,一個請求從 a層n發出,沿著 a
層 n -1 移動直到 a 層1(a的最底層),接著傳遞給 b 層1 (b的最底層)再沿著 b 層往上直到 b
層 n完成請求的回應沿著反方向傳遞。
實現:
以下的方法並非對所有的案例都是最好的,有時候採用從下而上或是溜溜球法會更好,所有的步驟並不是必須的,要看實際應用來判斷。
1.定義抽象準則來將任務分解成層,抽象準則往往來自平台概念上的區隔,如特定領域,概念複雜度等等。
e.g., 一個棋類遊戲可分為
遊戲整體策略
中盤戰術
基本移動
遊戲基本單位
e.g., 一般軟件可分為
用戶可見元素
特定應用模組
公共服務
操作系統介面
操作系統
硬體
2.根據抽象準則定義抽象層數。每個抽象層次對應模式中的一層,有時候抽象層次到層的映射是不明顯的
在確定是否針對特定點分為2個層或是合併為1個層時需要多加注意,過多的層會增加開銷,過少的層會導致不好的設計。
3.命名每個層並指定任務。
最高層的任務是整個系統的任務,所有其他層的任務只作為最高層的助手。
4.指定服務。
最重要的原則為層間必須嚴格的彼此分離。不可以有跨層存取的情況。
把較多的服務放在高層往往比低層來的好。
5.細化分層
重複步驟1~4。在考慮隱含層及其服務之前往往不可能精確定義抽象準則。
通常是錯誤定義組件及其服務,後來再根據他們的使用關係強加上一層結構。
e.g., 一個新元件可能要求不只一個層的服務,違反了嚴格分層的原則。溜溜球法:重複交替從上而下以及從下而上的設計過程。
6.為每個層指定一個接口
層j 對層j+1 應該是一個黑盒設計,建立一個接口以提供所有層j 的服務並把該接口封裝在一個 facade 對象中。
7.建立獨立層
(獨立層為特定的某層)
如果一個獨立層很複雜,則它應該被分成幾個獨立元件。
8.指定相鄰層之間的通訊
層間通訊最常用的為推–模組(push model)。當層j 請求層 j-1 的服務時,任何要求的訊息都要作為服務調用的一部分來傳輸。相反的拉–模組(pull model)也很常用,使用的場合是底層自行從高層獲取可利用訊息,但拉模組會引入附加層和相鄰更高層的相依關係,要避免這層關係可以使用 callback 。
9.分離鄰接層
高層關心相鄰的底層,但底層並不關心用戶的身份。代表單向連接,當修改層j的服務,層j的改變可以忽略層j+1 的存在,上述的情況發生在從上而下。
若是從下而上,可以使用callback,高層要註冊底層的callback 方法。
10.設計錯誤處理策略
對 layer 來說錯誤處理比較麻煩,因為一個錯誤可以在它出現的層裡處理也可以送到高層。送到高層對於低層而言必須將錯誤轉換成對高層有意義的描述。根據經驗,盡可能在最低層處理錯誤。這可以防止高層被大量的錯誤以及錯誤處理代碼干擾。至少應該試著把相似錯誤類型歸類於更一般的錯誤類型,並僅傳播這些更一般的錯誤類型。
9.變體
1.鬆散分層系統(Relaxed Layered System):
層之間的約束較少,每個層可以使用比它低層的所有服務,而不僅是相鄰層。
可以增加使用的靈活性和性能,但代價是維護性。適用於要求性能高的系統。
2.通過繼承分層(Layering Through Inheritance):
底層作為基本類別,高層繼承自底層。
優點是高層可以根據需要修改底層的服務,缺點為高層和底層透過繼承綁定,底層若有修改高層必須重新編譯(脆弱基類問題)。
10.已知使用
1.虛擬機: 虛擬機可以說是一種低層次的實現,它將低層次的細節或各類的硬體與高層次分離開來。
2.API: API可以說是一個封裝底層常用功能的層。
3.訊息系統(Information System):IS 一開始往往使用2層式體系結構,底層是一個數據庫存有公司的特殊數據,頂層為用戶介面。
用戶介面數據庫 |
因為用戶邏輯會摻雜商業邏輯,因此可以再分一層為商業邏輯層
用戶介面商業邏輯 數據庫 |
但越來越多的數據庫需要支援,因此再新增一層領域層來對不同數據庫增加支援
用戶介面商業邏輯 領域層 數據庫 |
4. Windows NT
該操作系統是根據微核模式來建構。NT執行程序元件對應微核模式的微核元件。NT執行程序是一個鬆散分層系統。
系統服務層:子系統和NT執行系統之間的接口層。資源管理器層:包含對象管理器,安全引用監視器,過程管理器,I/O管理器,虛擬儲存管理器等等。 內核層:一些基本功能,中斷和意外處理,多處理器同步,線程調度和分配。 HAL(硬體抽象層):隱藏不同處理器之間的硬體差異。 硬體層:硬體 |
11.效果:
分層體系模式的優點
1.加強層的復用:如果一個層定義良好的抽象介面,可在多個環境中重用。
2.增加標準化:定義清楚的層可以促進標準化的開發。
3.限制相依性:層之間的改變被限制在該層中,不會影響其他的層,也增加了可移植性,測試性。
單層可被簡易的替換,可採用 Adapter pattern 或是 Bridge Pattern 。
4.增加可替換性:但如果想對2個介面以及服務不完全相配的層之間切換,則必須在2個層之間加上建立一個隔離層。
層的缺點:
1.更改行為的重複:如果不得不在許多層上做相當數量的重複工作以適應局部變動。
2.降低效率:分層體系效率通常低於整塊模組的效率。如果最高層有很大的程度依賴最底層,所有數據都必須通過中間層的轉換。
3.不必要的工作:如果底層的服務重複執行了多餘的工作,而這些工作並非高層所需。
4.難以確認分層的正確度:層數太少的分層不能完全發揮分層體系的優勢(可重用性,可更改性,可移植性)。