一、裝飾者模式的應用場景
裝飾者模式(Decorator Pattern)是指在不改變原有對象的基礎上,將功能附加到對象上,提供了比繼承更有彈性的方案(擴展原有對象的功能),屬於結構型模式。裝飾者模式適用於以下場景:
- 擴展一個類的功能或給一個類添加附加職責。
- 動態給一個對象天機功能,這些功能可以再動態的撤銷。
以做煎餅果子為例演示裝飾者模式是怎么裝的:
首先做一個煎餅果子抽象:
public abstract class Battercake { protected abstract String getMsg(); protected abstract Integer getPrice(); }
然后,做一個基本的煎餅果子:
public class BaseBattercake extends Battercake{ @Override protected String getMsg() { return "煎餅"; } @Override protected Integer getPrice() { return 5; } }
創建擴展套餐的抽象裝飾者:
public class BattercakeDecorator extends Battercake { //靜態代理 委派 private Battercake battercake; public BattercakeDecorator(Battercake battercake) { this.battercake = battercake; } @Override protected String getMsg() { return battercake.getMsg(); } @Override protected Integer getPrice() { return battercake.getPrice(); } }
創建加雞蛋裝飾類:
public class EggDecorator extends BattercakeDecorator { public EggDecorator(Battercake battercake) { super(battercake); } @Override protected String getMsg() { return super.getMsg() + "add an egg"; } @Override protected Integer getPrice() { return super.getPrice() + 1; } }
客戶端:
public class BattercakeTest { public static void main(String[] args) { //基本版 Battercake battercake = new BaseBattercake(); //加蛋 battercake = new EggDecorator(battercake); //再加 battercake = new EggDecorator(battercake); //跟靜態代理區別在於靜態代理不是is-a關系 晶體代理會做功能增強,使同一個職責變得不一樣 //裝飾者模式更多考慮擴展 } }
二、裝飾者模式和適配器模式對比
裝飾者模式和適配器模式都是包裝模式(Wrapper Pattern),裝飾者模式是一種特殊的代理模式,二者對比如下:
裝飾者模式 | 適配器模式 | |
形式 | 是一種非常特別的適配器 | 沒有層級關系,裝飾者模式有層級關系 |
定義 | 裝飾者和被裝飾着實現同一接口,主要目的是為了擴展后依舊保留舊的oop關系 | 適配器和被適配這沒有必然的關系,通常采用繼承或代理的形式進行包裝 |
關系 | 滿足is-a關系 | 滿足has-a關系 |
功能 | 注重覆蓋、擴展 | 注重兼容、轉換 |
設計 | 前置考慮 | 后置考慮 |
三、裝飾模式在源碼中的應用
JDK中的I/O,如BufferReader,InputStream,OutputStream.Spring的緩存,myabtis的TransactionalCache(事物相關緩存):
public class TransactionalCache implements Cache { private static final Log log = LogFactory.getLog(TransactionalCache.class); private final Cache delegate; ... public TransactionalCache(Cache delegate) { this.delegate = delegate; ... } ... }
四、裝飾者模式的優缺點
優點:
- 裝飾者模式是繼承的有力補充,比繼承靈活,可以再不原有對象的情況下動態的給一個對象擴展功能,即插即用。
- 使用不同的裝飾類及這些裝飾類的排列組合,可以實現不同的效果。
- 裝飾者模式完全符合開閉原則。
缺點:
- 動態裝飾時,多層裝飾會更復雜。
- 增加復雜度,復雜度等等吧那些廢話。