裝飾模式的定義
裝飾模式(Decorator Pattern)是一種比較常見的模式,其定義如下:
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.(動態地給一個對象添加一些額外的職責。就增加功能來說,裝飾模式相比生成子類更為靈活。)
在類圖中,有四個角色需要說明:
Component抽象構件。Component是一個接口或者是抽象類,就是定義我們最核心的對象,也就是最原始的對象。裝飾模式中,必然有一個最基本、最核心、最原始的接口或抽象類充當Component抽構件。
ConcreteComponent具體構件。ConcreteComponent是最核心、最原始、最基本的接口或抽象類的實現,你要裝飾的就是它。
Decorator裝飾角色一般是一個抽象類,做什么用呢?實現接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的屬性里必然有一個private變量指向Component抽象構件。
具體裝飾角色ConcreteDecoratorA和ConcreteDecoratorB是兩個具體的裝飾類,你要把你最核心的、最原始的、最基本的東西裝飾成其他東西。
裝飾模式應用
裝飾模式的優點
裝飾類和被裝飾類可以獨立發展,而不會相互耦合。換句話說,Component類無須知道Decorator類,Decorator類是從外部來擴展Component類的功能,而Decorator也不用知道具體的構件。
裝飾模式是繼承關系的一個替代方案。我們看裝飾類Decorator,不管裝飾多少層,返回的對象還是Component,實現的還是is-a的關系。裝飾模式可以動態地擴展一個實現類的功能,這不需要多說,裝飾模式的定義就是如此。
裝飾模式的缺點
對于裝飾模式記住一點就足夠了:多層的裝飾是比較復雜的。為什么會復雜呢?你想想看,就像剝洋蔥一樣,你剝到了最后才發現是最里層的裝飾出現了問題,想象一下工作量吧,因此,盡量減少裝飾類的數量,以便降低系統的復雜度。
裝飾模式的使用場景
要擴展一個類的功能,或給一個類增加附加功能。需要動態地給一個對象增加功能,這些功能可以再動態地撤銷。需要為一批的兄弟類進行改裝或加裝功能,當然是首選裝飾模式。
最佳實踐
裝飾模式是對繼承的有力補充。你要知道繼承不是萬能的,繼承可以解決實際的問題,但是在項目中你要考慮諸如易維護、易擴展、易復用等,而且在一些情況下你要是用繼承就會增加很多子類,而且靈活性非常差,那當然維護也不容易了,也就是說裝飾模式可以替代繼承,解決我們類膨脹的問題。
同時,你還要知道繼承是靜態地給類增加功能,而裝飾模式則是動態地增加功能,如果你用繼承就必須修改程序。
裝飾模式還有一個非常好的優點:擴展性非常好。在一個項目中,你會有非常多的因素考慮不到,特別是業務的變更,不時地冒出一個需求,尤其是提出一個令項目大量延遲的需求時,那種心情是相當的難受!裝飾模式可以給我們很好的幫助,通過裝飾模式重新封裝一個類,而不是通過繼承來完成,簡單點說,三個繼承關系Father, Son, GrandSon三個類,我要在Son類上增強一些功能怎么辦?我想你會堅決地頂回去!不允許,對了,為什么呢?你增強的功能是修改Son類中的方法嗎?增加方法嗎?對GrandSon的影響呢?特別是GrandSon有多個的情況,你會怎么辦?這個評估的工作量就夠你受的,所以這是不允許的,那還是要解決問題的呀,怎么辦?通過建立SonDecorator類來修飾Son,相當于創建了一個新的類,這個對原有程序沒有變更,通過擴展很好地完成了這次變更。