41

装饰器模式是类在运行时的动态扩展。它动态地形成一个 is-a 关系。

在我得到这个关于 mixin 和抽象类之间区别的答案后,我开始怀疑我是否使用装饰器模式使我的 API 过于复杂。

4

2 回答 2

20

当您向班级添加一些行为时,mixin 很合适。例如,在集合类型的情况下枚举的能力。您可以根据需要将任意多的行为集混合到您的类中。它是重用通用代码的好方法;您基本上可以免费获得一堆方法。

另一方面,装饰器更像是一个偷偷摸摸的拦截器。它公开与目标对象相同的公共接口,包含一个目标对象,它将所有客户端调用委托给该对象;然而,它通过一些预处理和/或后处理来装饰调用。例如,如果我正在针对 MyCollection 编写代码,并且我希望记录对这种类型的所有调用。我可以派生一个新的装饰器 MyCollectionWithTimeStampedLogging 两者都派生自 ICollection 基础,以便它们看起来与客户端相同。装饰器将 ICollection 的实例作为 ctor 参数并委托对它的调用。例如添加看起来像这样

public void Add( int item)
{
  _logger.log(String.Format( "{0} Add called with param {1}", DateTime.Now, item.ToString());
  _collection.Add(item);
  _logger.log(String.Format( "{0} Add completed with param {1}", DateTime.Now, item.ToString());
}
于 2010-04-06T02:46:48.167 回答
18

使用装饰器模式时,您通常是封装,而不是扩展(或混入)基类。通常你这样做是因为你想使用类的功能,但你想包装对它的调用,这样你就可以在调用之前或之后做一些额外的步骤。考虑一个LoggerDecorator

public class LoggerDecorator implements SomeInterface {
      private SomeInterface delegate;
      public void someMethod() {
          LOGGER.debug("someMethod called");
          delegate.someMethod();
      }
}

您不想实际公开委托,但您想使用它的功能。因此,您是否使用 mixins、扩展类或装饰实际上取决于您要做什么。您是否正在扩展一个类并为其添加新功能?或者你在包装/装饰班级?

于 2010-04-06T02:31:05.587 回答