设计模式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个不同类,如果一个个继承的话……
当然,由于装饰者的特性,最好额外功能不要求特定的顺序,也就是说额外功能之间互不影响为最佳。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容