简体   繁体   English

在装饰器对象上调用未装饰的方法

[英]Calling non-decorated methods on decorator object

Suppose we have implemented the Decorator Pattern as in the image below. 假设我们已经实现了装饰器模式 ,如下图所示。 With the CondimentDecorator class, the Beverage class can be decorated. 使用CondimentDecorator类,可以装饰Beverage类。 The methods cost() and getDescription() will take care for that. 方法cost()getDescription()会注意这一点。

在此处输入图片说明

When creating a decorated Beverage like below, calling the method getName() won't work on the decorated object. 当创建如下所示的装饰饮料时 ,调用方法getName()不适用于装饰对象。 In order to make this work, this method should also be placed in the class CondimentDecorator and delegate the call to the composed beverage variable. 为了完成这项工作,还应该将该方法放在CondimentDecorator类中,并将调用委托给组合的Drink变量。

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

When having a lot of methods which don't need decoration, all of these should also be placed in CondimentDecorator to simply delegate. 当有很多不需要修饰的方法时,所有这些方法也都应该放在CondimentDecorator中以简单地委派。 So the question is: What is a neat (generally accepted) way to solve this 'problem'? 因此问题是: 解决此“问题”的一种整洁(通常被接受)的方法是什么?

The generally accepted approach to this 'problem' in a statically typed language like Java or C# (yes, C# is not quite statically typed, I know about DLR, and dynamic) is to have the decorated methods delegate to the decorated object explicitly . 对于像Java或C#这样的静态类型语言(是的,C#不是完全静态类型的,我知道DLR和动态的),这种“问题”的普遍接受的方法是让装饰方法明确地委派给装饰对象。 This solution has the obvious benefits of simplicity and explicitness . 该解决方案具有简单明显的利益。

In your example, if you don't override getName it means that you want to change the behaviour of the decorated object, which is exactly the purpose of the decorator pattern. 在您的示例中,如果不重写getName则意味着您更改装饰对象的行为,这正是装饰器模式的目的。

If you would choose to delegate to the decorated object by default then it would appear as if inheritance was broken, since CondimentDecorator inherits from Beverage but does not use the methods of base class. 如果您选择默认情况下委托给装饰对象则它看起来好像继承已中断,因为CondimentDecorator继承自Beverage,但未使用基类的方法。

Then, to change this behaviour, you would somehow need to define the methods that are not delegated to decorated object, but should work "as usual inheritance". 然后,要更改此行为,您将需要以某种方式定义未委托给装饰对象的方法,但应“照常继承”工作。 That would be not obvious and very messy. 那将是不明显的并且非常混乱。

That being said, what you want to achieve should be possible in Java. 话虽如此,您想要实现的目标应该可以在Java中实现。

For instance in .NET you could do this in the following ways, and I believe Java has something similar 例如,在.NET中,您可以通过以下方式进行操作,我相信Java具有类似的功能

  1. By generating dynamic runtime proxies that use inheritance to dynamically modify the behaviour of the object, see Castle Dynamic Proxy 通过生成使用继承来动态修改对象行为的动态运行时代理,请参阅城堡动态代理。
  2. By using a MSIL rewriting technique that rewrites your itermediate code at compile time to modify it, for example see Fody - Method decorator 通过使用MSIL重写技术,该技术在编译时重写您的中间代码以对其进行修改,例如,请参见Fody-方法装饰器

Additionally, check out how prototypical inheritance works in JavaScript - that behaviour is very similar to what you're trying to achieve 此外,请检查原型继承在JavaScript中的工作方式-该行为与您要实现的行为非常相似

In your case if only few operation1() it is ok to add a delegate call to CondimentDecorator. 在您的情况下,如果只有几个operation1(),可以将委托调用添加到CondimentDecorator。 If only few call() needs decoration then could make a decorator when needed, like: DecoratorFactory.make(new Milk(new Espresso("A very nice espresso"))).getDescription(); 如果只有很少的call()需要装饰,则可以在需要时制作装饰器,例如:DecoratorFactory.make(new Milk(new Espresso(“ Espresso”)))。getDescription();

or 要么

CondimentDecorator.getDescription(new Milk(new Espresso("A very nice espresso"))); CondimentDecorator.getDescription(new Milk(new Espresso(“ A a great nice espresso”))));

Key: patterns serve you. 重点:模式为您服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM