在decorator对象上调用非修饰方法

时间:2017-03-24 16:59:53

标签: java design-patterns decorator

假设我们已经实现了装饰器模式,如下图所示。使用 CondimentDecorator 类,可以装饰 Beverage 类。方法cost()getDescription()将照顾到这一点。

enter image description here

在创建如下所示的装饰 Beverage 时,调用 getName()方法不会对装饰对象起作用。为了使这项工作,这个方法也应放在 CondimentDecorator 类中,并将调用委托给组合的饮料变量。

Beverage b = new Milk(new Espresso("A very nice espresso"));
b.getName() // returns null

当有很多不需要装饰的方法时,所有这些方法也应放在 CondimentDecorator 中以简单委托。所以问题是:什么是解决这个问题的整洁(普遍接受)的方式'

2 个答案:

答案 0 :(得分:1)

这个问题的普遍接受的方法&#39;在一个静态类型语言中,如Java或C#(是的,C#不是静态类型,我知道DLR和动态)是将装饰方法委托给装饰对象显式< / strong>即可。此解决方案具有简单显式性的明显优势。

在您的示例中,如果您不重写getName,则表示您想要更改已修饰对象的行为,这正是装饰器模式的目的

如果您选择默认委托装饰对象 ,那么看起来好像继承被破坏了,因为CondimentDecorator继承自Beverage但不使用基类方法。

然后,要改变这种行为,你会以某种方式需要定义未委托给装饰对象的方法,但是应该像通常的继承一样工作&#34;。 那不是很明显也很混乱。

话虽如此,你想要实现的目标应该是Java。

例如在.NET中你可以通过以下方式实现这一点,我相信Java有类似的东西

  1. 通过生成使用继承来动态修改对象行为的动态运行时代理,请参阅Castle Dynamic Proxy
  2. 使用MSIL重写技术在编译时重写您的itermediate代码以修改它,例如,请参阅Fody - Method decorator
  3. 此外,请查看prototypical inheritance works in JavaScript -该行为与您尝试实现的行为非常相似的方式

答案 1 :(得分:0)

在您的情况下,如果只有少数operation1(),则可以向CondimentDecorator添加委托调用。如果只有少数call()需要装饰,那么可以在需要时制作装饰器,例如: DecoratorFactory.make(新牛奶(新浓缩咖啡(“非常好的咖啡”)))。getDescription();

CondimentDecorator.getDescription(新牛奶(新浓缩咖啡(“非常好的咖啡”)));

关键:模式为您服务。