Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 装饰器可以是组件的直接子级吗?_Design Patterns_Decorator - Fatal编程技术网

Design patterns 装饰器可以是组件的直接子级吗?

Design patterns 装饰器可以是组件的直接子级吗?,design-patterns,decorator,Design Patterns,Decorator,查看wikipedia()上的Decorator模式页面,布局如下所示: ThingDoer thingDoer = new BaseThingDoerDecorator(new AwesomeThingDoer()) { @Override public void doThing() { System.out.println("This is an anonymous decorator"); super.doThing(); } };

查看wikipedia()上的Decorator模式页面,布局如下所示:

ThingDoer thingDoer = new BaseThingDoerDecorator(new AwesomeThingDoer()) {
    @Override
    public void doThing() {
        System.out.println("This is an anonymous decorator");
        super.doThing();
    }
};
  • 组件接口
  • 组件实现
  • 实现组件接口的装饰器接口
  • 实现Decorator接口的Decorator

decorator是否可以直接实现组件接口(并跳过decorator接口)?

以下是您引用的wikipedia页面中的UML图:

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


也就是说,任何ConcreteDecorator都可以直接从组件继承(如果您的设计使用接口,则可以实现其接口),而无需使用Decorator抽象类。但是,所有ConcreteDecorator都需要聚合一个组件,因此,如果您有多个ConcreteDecorator,那么抽象类可能有助于避免重复代码。

使用Decorator模式的主要好处是,对于客户端代码,它是透明的。他们不需要了解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);
        }
    }
}

这个问题是关于哪种编程语言的?这应该适用于任何支持继承或接口的语言。为什么要问?@neverendingqs没有装饰器接口,有一个可选的抽象装饰器。@qujck接口不是纯抽象类(无论如何,在功能上)?为什么它必须是一个抽象的装饰器?@qujck我也认为你回答了这个问题=PI实际上认为这个图是错误的。如果模式是以这种方式实现的,那么每个装饰器将有2个组件。避免不必要的开销的唯一方法是使基本组件(装饰器“是”的组件)完全为空-这使它成为除名称之外的所有接口。这可能是一种有效的方法,可以将它硬塞进没有接口的语言中,但这会产生误导,当然不应该用于模式的权威模型。我只看到一个组件@Floegipoky。第二个在哪里?装饰器“包装”组件,所以我不认为接口代替装饰器有什么意义。这里的设计看起来像是GoF的设计,它是在Java或C#接口出现之前提出的。请引用您的权威参考@floegipokya根据此图,每个decorator都有它聚合的组件(它包装的组件)和它通过继承获得的组件。如果基本组件持有任何类型的状态,每个组件将持有2个副本。好的,那么您要计算继承(“是a”)和聚合(“有a”)。Java的Java.io类以这种方式使用Decorator,例如BufferedInputStream和LineNumberInputStream都扩展了FilterInputStream,后者充当抽象Decorator类。它们都是抽象类的子类。理论上可能存在复制状态,但我认为这是值得的。当然,我假设Liskov替换原则得到尊重。为了澄清@Floegipoky,答案是:“是的,装饰器是组件的直接子级。但是,这里有一些示例,您希望使用抽象类。”?@neverendingqs不,我的答案是装饰器必须实现组件接口,但是这里有一些例子,它们也可以从基类继承。嗯,这就是我的意思,但是我的语法和措辞在这个问题上不是最好的。不管怎样,你的回答澄清了我在寻找什么。