Design patterns 装饰器可以是组件的直接子级吗?
查看wikipedia()上的Decorator模式页面,布局如下所示: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(); } };
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不,我的答案是装饰器必须实现组件接口,但是这里有一些例子,它们也可以从基类继承。嗯,这就是我的意思,但是我的语法和措辞在这个问题上不是最好的。不管怎样,你的回答澄清了我在寻找什么。