装饰者可以成为组件的直接子项吗?

时间:2015-01-01 22:48:34

标签: design-patterns decorator

查看维基百科(http://en.wikipedia.org/wiki/Decorator_pattern)上的Decorator模式页面,布局如下所示:

  • 组件接口
  • 组件实施
  • 实现组件接口的Decorator接口
  • 实现装饰器界面的装饰者

装饰器可以直接实现组件接口(并跳过装饰器界面)吗?

2 个答案:

答案 0 :(得分:0)

这是您引用的维基百科页面中的UML图:

Decorator pattern in UML

在此图中,Decorator 不是一个接口,而是一个抽象类。组件也是此图中的接口(因为从其继承的ConcreteComponent和 Decorator 类不具有图中箭头的虚线)。我知道这是一个细节,但UML具体是有原因的。

也就是说,任何ConcreteDecorator都可以直接从Component继承(或者如果你的设计使用接口,则实现它的接口),而不使用 Decorator 抽象类。但是,所有 ConcreteDecorators需要聚合一个组件,因此如果您有多个ConcreteDecorator,抽象类可能对避免重复代码很有用。

答案 1 :(得分:0)

使用Decorator模式获得的主要好处是,对于客户端代码,它是透明的。他们不需要了解装饰器,他们可以像对待基本接口的简单旧具体实现一样对待它:

ThingDoer thingDoer = new ThingDoerDecorator(new AwesomeThingDoer());
ThingDoer otherThingDoer = new AwesomeThingDoer();

thingDoer.doThing();
otherThingDoer.doThing();

这是唯一可能的,因为装饰器实现了与它装饰相同的界面。如果它没有实现这个界面你会失去这种模式的大部分功能

但是,有时候有一个基础装饰器实现

abstract class BaseThingDoerDecorator implements ThingDoer {
    private ThingDoer thingDoer;

    protected BaseDecorator(ThingDoer thingDoer) {
        this.thingDoer = thingDoer;
    }

    @Override
    public void doThing() {
        thingDoer.doThing();
    }
}

现在做这样的事情变得切实可行了:

ThingDoer thingDoer = new BaseThingDoerDecorator(new AwesomeThingDoer()) {
    @Override
    public void doThing() {
        System.out.println("This is an anonymous decorator");
        super.doThing();
    }
};

或许您希望所有装饰器都不受基本组件中的异常的影响:

abstract class BaseThingDoerDecorator implements ThingDoer {
    // Same as above...
    // ...
    @Override
    public void doThing() {
        try {
            thingDoer.doThing();
        } catch (Exception e) {
            log(e);
        }
    }
}