为什么我们需要装饰器设计模式中的装饰器?

假设我有一个名为A的类,我想使用装饰器设计模式。 如果我错了,请纠正我,但为了工作,我们需要创建一个装饰器类,比如ADecorator ,它将保存对A实例的引用,所有其他装饰器将扩展它以添加function。

我不明白为什么我们必须创建一个装饰器类,而不是使用A实例?

装饰器模式用于动态地向对象添加function(即,在运行时)。 通常,在编写类时,对象的function会得到修复。 但重要的一点是,对象的function以对对象客户端透明的方式扩展,因为它实现了与原始对象将责任委托给装饰对象相同的接口。

装饰器模式适用于对象可能具有许多可选function的场景。 如果没有装饰器模式,则必须为每个对象选项配置创建不同的类。 一个非常有用的例子来自O’Reilly的Head First Design Patterns一书。 它使用的咖啡店就像StarBucks一样。

因此,您可以使用成本等方法获得基本咖啡。

 public double cost(){ return 3.45; } 

然后客户可以添加0.35的奶油,因此您现在使用成本方法创建CoffeeCream类:

 public double cost(){ return 3.80; } 

然后顾客可能想要Mocha,其成本为0.5,他们可能想要Mocha with Cream或Mocha without Cream。 所以你创建了CoffeeMochaCream和CoffeeMocha类。 然后客户想要双奶油,所以你创建了一个类CoffeeCreamCream …等你最终得到的是类爆炸。 请原谅使用的不好的例子。 这有点晚了,我知道这是微不足道的,但确实表明了这一点。

相反,您可以使用抽象成本方法创建Item抽象类:

 public abstract class Item{ public abstract double cost(); } 

你可以创建一个扩展Item的具体Coffee类:

 public class Coffee extends Item{ public double cost(){ return 3.45; } } 

然后创建一个CoffeeDecorator,它扩展相同的接口并包含一个Item。

 public abstract class CoffeeDecorator extends Item{ private Item item; ... } 

然后,您可以为每个选项创建具体的装饰器:

 public class Mocha extends CoffeeDecorator{ public double cost(){ return item.cost() + 0.5; } } 

请注意,只要它是一个Item,装饰器如何不关心它包装的对象类型? 它使用item对象的cost()并简单地添加自己的成本。

 public class Cream extends CoffeeDecorator{ public double cost(){ return item.cost() + 0.35; } } 

现在可以使用这几个类来进行大量配置:例如

  Item drink = new Cream(new Mocha(new Coffee))); //Mocha with cream 

要么

  Item drink = new Cream(new Mocha(new Cream(new Coffee))));//Mocha with double cream 

等等。

我无法解释它比维基百科文章更好。

顺便说一句,如果你刚刚开始使用模式,那么Head First Design Patterns一书是非常出色的。 它确实使概念易于消化,并确保以一种非常容易理解的方式对比和比较相似的模式。

在某些语言(如Ruby或JavaScript)中,您只需向A实例添加新function即可。 我注意到你的问题被标记为Java,所以我假设你问为什么你不能用Java做这个。 原因是Java是静态类型的。 A实例只能拥有类A定义或inheritance的方法。 因此,如果您希望在运行时为A实例提供A未定义的方法,则必须在不同的类中定义此新方法。