
原文地址:LoveDev
裝飾模式(Decorator Pattern):也可以稱為包裝模式(Wrapper Pattern),它動態(tài)給一個對象增加額外的職責(zé),就增加對象功能來說,裝飾模式比生成子類實現(xiàn)更為靈活,它是一種對象結(jié)構(gòu)型模式。
裝飾模式是一種用于替代繼承的技術(shù),通過一種無須定義子類的方式給對象動態(tài)增加職責(zé),使用對象間的關(guān)聯(lián)關(guān)系替代繼承關(guān)系

- Component(抽象組件類):具體組件類和抽象裝飾類共同父類,聲明了具體組件中需要實現(xiàn)的方法,它的引入可以使調(diào)用者以一致的方式處理未裝飾對象和裝飾對象,實現(xiàn)調(diào)用者的透明操作
- ConcreteComponent(具體組件類):實現(xiàn)抽象組件類的聲明的方法
- Decorator(抽象裝飾類):用于增加具體組件的職責(zé),它的子類實現(xiàn)具體職責(zé),它持有一個具體組件類的引用,通過該引用可以調(diào)用未裝飾前的方法,并通過子類擴(kuò)展該方法
- ConcreteDecorator(具體裝飾類):給具體組件類增加新方法
平時生活中,有很多需要送禮物的時候,一個好禮物更需要好包裝來襯托,但是有時候買的禮物只有一個很丑陋的盒子,以裝飾模式實現(xiàn)包裝禮物的需求:
Component 類:
public abstract class Gift {
/**
* 禮物包裝
*/
public abstract void packaging();
}
ConcreteComponent 類:
public class BirthdayGift extends Gift {
@Override
public void packaging() {
LogUtils.i("包裝盒");
}
}
Decorator 類:
public abstract class GiftPackaging extends Gift {
private Gift gift;
public GiftPackaging(Gift gift) {
this.gift = gift;
}
public void packaging() {
gift.packaging();
}
}
ConcreteDecorator 類:
// 簡易包裝
public class SimplePackaging extends GiftPackaging {
public SimplePackaging(Gift gift) {
super(gift);
}
@Override
public void packaging() {
super.packaging();
addColorSheet();
}
private void addColorSheet() {
LogUtils.i("包彩紙");
}
}
// 奢華包裝
public class LuxuryPackaging extends GiftPackaging {
public LuxuryPackaging(Gift gift) {
super(gift);
}
@Override
public void packaging() {
super.packaging();
addColorSheet();
addRibbon();
addCard();
addGiftBox();
}
private void addColorSheet() {
LogUtils.i("包彩紙");
}
private void addRibbon() {
LogUtils.i("加彩帶");
}
private void addCard() {
LogUtils.i("加賀卡");
}
private void addGiftBox() {
LogUtils.i("加禮盒");
}
}
Client 類:
// 簡易包裝的禮物
Gift gift = new BirthdayGift();
Gift giftPackaging = new SimplePackaging(gift);
giftPackaging.packaging();
// 奢華包裝的禮物
Gift gift = new BirthdayGift();
Gift giftPackaging = new LuxuryPackaging(gift);
giftPackaging.packaging();
<h3> 透明裝飾模式 </h3>
上面實現(xiàn)的裝飾模式叫做透明裝飾模式,客戶端可以完全針對抽象編程,裝飾模式的透明性要求客戶端不應(yīng)該將對象類型聲明為具體組件類型或者具體裝飾類型,需要全部聲明為抽象組件類型,對于客戶端調(diào)用來說,具體組件對象和具體裝飾對象是一樣的,沒有任何區(qū)別,可以一致處理這些對象,實現(xiàn)透明裝飾模式時,要求具體裝飾類的 operation() 方法覆蓋抽象裝飾類的 operation() 方法,除了調(diào)用具體組件類的 operation() 方法外,還需要調(diào)用新增的 addedBehavior() 方法來增加新職責(zé)。
透明模式可以對一個已裝飾的對象再進(jìn)行裝飾,獲得更復(fù)雜,功能更強(qiáng)大的對象。
<h3> 半透明裝飾模式 </h3>
有透明裝飾模式,就有對應(yīng)的半透明裝飾模式,有時我們需要單獨調(diào)用新增方法,就不得不把對象聲明為具體裝飾類型,具體組件對象還是可以繼續(xù)定義為抽象組件類型,這就是半透明裝飾模式。
還是拿上面的栗子來說,如果包裝禮物只想用絲帶和彩紙包裝或者再加一個禮袋,用半透明模式就會非常方便靈活,直接調(diào)用對應(yīng)的方法就可以了,但是客戶端需要區(qū)別對待裝飾前后的對象
<h3> 優(yōu)點 </h3>
- 利用關(guān)聯(lián)關(guān)系替代繼承關(guān)系,更加靈活,不會導(dǎo)致類個數(shù)急劇增加
- 透明裝飾模式可以對一個對象進(jìn)行多次裝飾,通過使用不同的具體裝飾類的組合,能得到功能更加強(qiáng)大的對象
- 具體組件類和具體裝飾類可以獨立變化,根據(jù)需求,在不變原來代碼得基礎(chǔ)上,增加這兩個類,很符合“開閉原則”
<h3> 缺點 </h3>
- 既然是更加靈活的解決方法,出錯的幾率也隨之變大,排查錯誤的困難也跟著變大