装饰器命令模式(Decorated Command)

2004年1月24日

这是一种非常常见的模式,也很简单,它实际上就是应用于命令的装饰器模式。我见过它在面向命令的接口中被大量使用。你还会听到它被称为拦截器,以及面向方面编程的一种形式。

你从一些命令开始,通常是一些基本功能的形式,这些功能可能需要稍后添加一些附加功能。因此,这可能是一个面向领域的命令,例如 PayInvoice。这些命令将具有一些 execute 方法。

// psuedo C#
class PayInvoiceCommand : Command ...
void Execute() {
  // do interesting domain logic
}

假设我们想在事务中执行此操作。我们可以使用合适的事务装饰器来装饰命令。

// pseudo C#
class TransactionalDecorator : CommandDecorator ...
  void Execute() {
    Transaction t = TransactionManager.beginTransaction();
    try {
      Component.Execute();
      t.commit();
    } catch (Exception) {
      t.rollback();
    }
  }
    

我们也可以通过这种方式进行安全检查

// pseduo C#
class SecurityDecorator : CommandDecorator ...
  void Execute() {
    if (passesSecurityCheck())
      Component.Execute();
  }

有了这些类,我们就可以轻松地组合它们以获得正确的行为。

//psuedo C#
  // Transaction Invoice Payment
  Command c = new TransactionalDecorator(new PayInvoiceCommand(invoice));
  c.Execute();
  //Transactional and secure payment
  Command c = new SecurityDecorator(
                  new TransactionalDecorator(
                      new PayInvoiceCommand(invoice)));
  c.Execute();

事实上,这种动态添加行为的能力是面向命令的接口的一大优势。

现在很多东西都在面向方面的旗帜下做这种事情。在某个时候,我将更深入地研究这一点,看看除了这种模式之外是否还有其他模式在起作用。

这是面向方面的,但面向方面编程还有更多内容。在方面术语中,装饰器为域命令的 Execute 方法提供建议。但是,为了做到这一点,你必须围绕命令组织一切,因为只有 Execute 方法可以被建议。更灵活的 AOP 工具,例如 aspectJ,允许你建议*任何*方法,实际上还有一些其他的东西,例如字段访问。