使用列表而不是装饰器模式?

2022-09-01 19:26:26

“Head First: Design Patterns”一书中的装饰器模式用例让我有了这个问题。我会试着把它写下来:

这是一个咖啡店系统,里面有一些咖啡和很多调味品,你可以把它们放进去(需要额外付费),你需要能够订购咖啡和收费,里面有顾客想要的任何调味品,并且为了避免完全混乱(例如,布尔值来跟踪调味品),使用装饰器图案。我们有一个抽象的饮料类,每种类型的咖啡作为混凝土成分,每种调味品作为混凝土装饰器包装饮料,如下所示:

Beverage Class Diagram

因此,我们有以程返回咖啡成本:

Coffee Cost Delegation

我的问题是:为什么不用列表而不是装饰器来实现这一点呢?我们可以在每种饮料中列出调味品,并通过迭代列表来计算成本。要订购咖啡,我们只需要将其实例化一次并添加所需的调味品,避免如下声明:

// Using second image example
Beverage beverage = new DarkRoast(beverage);
beverage = new Mocha(beverage);
beverage = new Whip(beverage);

除此之外,我们还将有更大的灵活性来操作,例如为不包括调味品的咖啡提供折扣,一旦我们没有装饰师包装咖啡。这是一个长期研究的问题,我知道我错过了一些东西,或者我做错了什么,所以如果你对此有任何想法,我很想知道并进一步讨论。


答案 1

Decorator模式是关于在运行时用额外的功能装饰(增强)一个对象。

假设您已经有一个类,让我们将其称为实现接口的类。现在,如果需要添加一个附加功能,我们希望它具有 方法 ,这在 .现在,您可以选择扩展类。另一种方法是应该比 .您可以将类的对象包装在另一个类中,使其与 i.(即 ) 相同。这种方式对于客户端代码来说很容易接受类B的对象,因为它具有与A相同的接口(假设代码写得很好,这取决于抽象(接口),而不是像类这样的具体类)。AIAsomeAlignFeatureToA()AACompositionInheritanceABInterfaceAIAIAA

这样,继承链就不会太长,您可以在运行时轻松添加其他功能。

现在来谈谈你的问题:是的,在你提出的问题中,列表更适合,但我觉得作者的意图是用一个简单的例子来解释装饰者模式的使用。假设咖啡由牛奶,咖啡混合物和糖组成。咖啡混合物还由较小的成分组成。在这里,解决方案类似于复合模式。

装饰器模式是基于行为增强的设计模式。Java IO流使用它,其中行为(方法实现)由装饰类增强(一个流与另一个流包装以增强前一个流)


答案 2

您讲述的是一种计算饮料总成本的方法。更一般地说,您提出了一种替代方法来合并和执行装饰器模式所假设的每个派生对象的主要行为,方法是将它们添加到列表中。而且它也不是一种OO方法。

装饰者模式的初衷是更广阔的视角。它是动态地向对象添加扩展功能。这意味着我有一些对象,我希望它将其转换为具有扩展功能的另一个对象,并且尚未成为这2个可互换的对象。O1O2

因此,它是关于我们如何根据对象生命周期管理对象演变。希望你有这个想法。:))