設計模式3:裝飾模式

裝飾模式(Decorator Pattern)能動態附加對象的功能,裝飾器提供了比繼承更為靈活的擴展方案。
這個模式是繼承的一種代替方案。
一般而言,這個模式的底層是一個接口或者是抽象類。然后還需要裝飾類來擴展該接口或者繼承抽象類,并進行“聚合”操作。也就是說,裝飾類是在原有的功能上附加額外的功能。
還是來看代碼吧:

Troll接口,意思是怪物?巨魔?有三個函數。

/**
 * 
 * Interface for trolls
 *
 */
public interface Troll {

  void attack();

  int getAttackPower();

  void fleeBattle();

}

然后SimpleTroll類,使用Troll接口。

/**
 * 
 * SimpleTroll implements {@link Troll} interface directly.
 *
 */
public class SimpleTroll implements Troll {

  private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTroll.class);

  @Override
  public void attack() {
    LOGGER.info("The troll tries to grab you!");
  }

  @Override
  public int getAttackPower() {
    return 10;
  }

  @Override
  public void fleeBattle() {
    LOGGER.info("The troll shrieks in horror and runs away!");
  }
}

裝飾類TrollDecorator,可以看到,它不僅是使用了Troll接口,自己還另外帶一個,并把接口函數全都委托給另帶的那個。

/**
 * TrollDecorator is a decorator for {@link Troll} objects. The calls to the {@link Troll} interface
 * are intercepted and decorated. Finally the calls are delegated to the decorated {@link Troll}
 * object.
 *
 */
public class TrollDecorator implements Troll {

  private Troll decorated;

  public TrollDecorator(Troll decorated) {
    this.decorated = decorated;
  }

  @Override
  public void attack() {
    decorated.attack();
  }

  @Override
  public int getAttackPower() {
    return decorated.getAttackPower();
  }

  @Override
  public void fleeBattle() {
    decorated.fleeBattle();
  }
}

一個具體的裝飾實現,繼承裝飾類,調用超類的基礎上再自己加入一些東西,而超類的實現也就是外帶的Troll接口實現,這樣就在原有Troll之外增加了功能。

/**
 * Decorator that adds a club for the troll
 */
public class ClubbedTroll extends TrollDecorator {

  private static final Logger LOGGER = LoggerFactory.getLogger(ClubbedTroll.class);

  public ClubbedTroll(Troll decorated) {
    super(decorated);
  }

  @Override
  public void attack() {
    super.attack();
    LOGGER.info("The troll swings at you with a club!");
  }

  @Override
  public int getAttackPower() {
    return super.getAttackPower() + 10;
  }
}

你也許會問:這不還是繼承嗎?確實用到了繼承,但和單純使用繼承來擴展功能還是有很大區別的。區別是什么呢?就是運行時可以改變類的行為。

public static void main(String[] args) {

    // simple troll
    LOGGER.info("A simple looking troll approaches.");
    Troll troll = new SimpleTroll();
    troll.attack();
    troll.fleeBattle();
    LOGGER.info("Simple troll power {}.\n", troll.getAttackPower());

    // change the behavior of the simple troll by adding a decorator
    LOGGER.info("A troll with huge club surprises you.");
    Troll clubbed = new ClubbedTroll(troll);
    clubbed.attack();
    clubbed.fleeBattle();
    LOGGER.info("Clubbed troll power {}.\n", clubbed.getAttackPower());
  }
}

SimpleTroll就是普通的一個Troll,給它套上ClubbedTroll裝飾,馬上就有了ClubbedTroll的功能。以此類推,還可以加別的裝飾。這又是和繼承的另一個重要的區別:自由組合。
N個裝飾者總共可以產生2^N個不同類,如果一個個繼承的話……
當然,由于裝飾者的特性,最好額外功能不要求特定的順序,也就是說額外功能之間互不影響為最佳。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容