天天看點

[設計模式筆記]二. 結構型模式--10.Decorator模式(裝飾模式)(一)一. 意圖二. 适用性三. 模式結構四. 角色說明五. 說明六. 我的了解七. 相關模式

Decorator(裝飾)模式(對象結構型模式)

一. 意圖

動态地給一個對象添加一些額外的職責. 就增加功能來說, Decorator模式相比生成子類更為靈活.

二. 适用性

1. 在不影響其他對象的情況下, 以動态, 透明的方式給單個對象添加職責.

2. 處理那些可以撤消的職責.

3. 當不能采用生成子類的方法進行擴充時. 一種情況是, 可能有大量獨立的擴充, 為支援每一種組合将産生大量的子類, 使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隐藏, 或類定義不能用于生成子類.

三. 模式結構

[設計模式筆記]二. 結構型模式--10.Decorator模式(裝飾模式)(一)一. 意圖二. 适用性三. 模式結構四. 角色說明五. 說明六. 我的了解七. 相關模式

圖1 

四. 角色說明

Component

—定義一個對象接口,可以給這些對象動态地添加職責。

ConcreteComponent

—定義一個對象,可以給這個對象添加一些職責。

Decorator

—維持一個指向Component對象的指針, 并定義一個與Component接口一緻的接口.

ConcreteDecorator

—向元件添加職責

Decorator将請求轉發給它的Component對象, 并有可能在轉發請求前後執行一些附加的動作.

五. 說明

對一個已經封裝好的功能增加功能, 因為已經封裝好了, 你不可能在它的内部進行修改. 現在就有兩種方式: 

1. 使用繼承, 生成一個該功能的子類. 這個子類的要求肯定是要實作父類的接口(父類公開出來的方法).(因為父類已經在用了).

然後對父類對應的方法進行功能擴充.(在父類的方法裡面你喜歡怎樣就怎樣了).

2. 生成一個類, 該類包含該原功能類的對象. 這個類同樣實作原功能類的接口.(新類中對應的接口調用對象對應的接口).

(新類與功能類繼承與同一接口, 這樣原來的使用者就不需要改動代碼.)(這就是Decorator模式了)

使用Decorator模式時應注意以下幾點:

1. 接口的一緻性 裝飾對象的接口必須與它所裝飾的Component的接口是一緻的, 是以,所有的ConcreteDecorator類必須有一個公共的父類.

2. 沒有抽象的Decorator類, 因為你常常需要處理現存的類層次結構而不是設計一個新系統, Decorator與ConcreteComponent位于同一類層次即可(繼承于同一父類). 

3. 保持Component類的簡單性 為了保證接口的一緻性, 元件和裝飾必須有一個公共的Component父類. 是以保持Component類的簡單性是很重要的: 即它應集中于定義接口而不是存儲資料. 對資料表示的定義應延遲到子類中, 否則Component類會變得過于複雜和龐大, 因而難以大量使用。賦予Component太多的功能也使得,具體的子類有一些它們并不需要的功能的可能性大大增加。

4. 改變對象外殼與改變對象核心, 我們可以将Decorator看作一個對象的外殼, 它可以改變這個對象的行為. 另外一種方法是改變對象的核心. 例如Strategy模式就是一個用于改變核心的很好的模式.

六. 我的了解

1. 有一個類, 你不能改變它的内部實作, 但是需要擴充它的功能.你可以使用一個新類, 新類包含一個原類的對象, 在調用對象的方法前後擴充它的功能. 有一個問題, 原類已經再使用了, 它的接口已經被客戶使用了. 我們擴充它的功能的前提是盡量的讓客戶少改代碼, 少改變. 如果原類的功能方法不是繼承接口的(原類沒有父類, 或者說原類提供給客戶的方法不是接口), 那Decorator模式無法使用的. ConcreteComponent與Decorator必須有相同的接口(要擴充功能所對應的那個接口).

[設計模式筆記]二. 結構型模式--10.Decorator模式(裝飾模式)(一)一. 意圖二. 适用性三. 模式結構四. 角色說明五. 說明六. 我的了解七. 相關模式

圖2

2. Decorator中包含一個ConcreteComponent對象, Decorator::Operation中調用ConcreteComponent::Operation.

而ConcreteDecorator::Operation調用Decorator::Operation (可以看到ConcreteComponent與ConcreteDecorator被Decorator隔開了解耦了).

這樣隔開, 效果非常明顯在類層次上, 我可以橫向的擴充ConcreteComponent的功能(增加ConcreteDecorator類). 如果使用縱向擴充(類繼承), 一條長長的類繼承鍊, That's not a good idea.

3. Decorator中定義的是一個Component指針, 而不是一個ConcreteComponent指針, 也就是Decorator不是針對某個ConcreteComponent類擴充, 而是可以針對所有的ConcreteComponent來擴充.(這一點可以區分Proxy代理模式: 它就是針對某個類的)

4. ConcreteDecorator::Operation中你可以根據你的需求随便修改, 甚至Decorator::Operation你也可以不調用, 看需求吧.

七. 相關模式

1. Adapter模式:Decorator模式不同于Adapter模式, 因為裝飾僅改變對象的職責而不改變它的接口; 而擴充卡将給對象一個全新的接口.

2. Composite模式: 可以将裝飾視為一個退化的, 僅有一個元件的組合. 然而, 裝飾僅給對象添加一些額外的職責—它的目的不在于對象聚集.

3. Strategy模式: 用一個裝飾你可以改變對象的外表; 而Strategy模式使得你可以改變對象的核心. 這是改變對象的兩種途徑.

繼續閱讀