关于java:这里真的需要装饰模式吗?

Is the decorator pattern really needed here?

本问题已经有最佳答案,请猛点这里访问。

我正在从《头一设计模式书》学习装饰设计模式。他们的例子把不同类型的咖啡当作饮料。饮料上装饰有牛奶、大豆、鲜奶油等。例如,黑咖啡加摩卡和鲜奶油:decorator example

类图:class diagram

我理解这个例子的使用只是因为它很简单。但是,我有一种替代的、更简单的方法来实现这个不使用decorator模式的示例。我们可以有一个带有描述和成本的项目类。然后,饮料类可以有基本成本、总成本和项目列表。

这种替代设计比装饰图案有什么主要缺点吗?你能给我一些具体的场景吗,在这些场景中,装饰图案会比我的设计更好?

PS-如果有人想要查看装饰代码:https://github.com/bethrobson/head-first-design-patterns/tree/master/src/headfirst/designpatterns/decorator/starbuzz


这个例子主要是关于如何使用decorator模式

Patterns can be a complex subject and knowing when to use them is sometimes more complicated than understanding how to use them

其他示例如Mat,其中向对象添加功能,例如颜色:

1
2
3
4
5
6
7
8
9
10
11
12
public class Mat extends ImageDecorator {
   String color;

   public Mat(String color, PhotoImage target) {
         super(target);
         this.color = color;
   }

   @Override
   public String getDescription() {
        return target.getDescription() +", Matted(" + color +")";
   }

这是使用decorator模式添加功能而不进行多重继承的主要原因。

The Decorator pattern provides a more flexible way to add responsibilities to objects than can be had with static (multiple) inheritance


在这里,一种特定的饮料基本上是由一个相关的成分列表来表示的。getDescription()方法递归地构建饮料的字符串表示。

在这个简单的例子中,它可能是可以的,但是如果有许多成分,可能有不同的数量,另一个数据结构可能会更好(可能是某种哈希表,但还有许多其他的可能性)。

例如,这里的数量是用重复的项目表示的(因此没有分数),例如,请参见starbuzcoffee.java中beverage2中的重复Mocha

您可以通过考虑管理另一个数据结构的开销,而不是链接列表的简单性,来决定哪个解决方案更好,记住,如果链接列表中有许多项,特别是需要对元素进行随机访问时,链接列表的成本可能很高。示例:您需要O(N)循环(其中N是列表大小)来检查饮料是否具有给定的成分,更不用说哈希表了。但是对于低n值,哈希表的解决方案可能会慢一些,因为它是一个更复杂的数据结构。

你的问题的答案取决于上下文,但一般来说,另一种方法没有错。


在这个例子中,在没有装饰器模式的情况下,可以有相同的行为。我同意别人已经说过的话。当然,这个例子只是为了学习如何与装饰师合作并识别模式。

我想在这里增加一点,我如何看待这个问题。(因为你说你在学习这个模式)

当您使用decorator模式时,它可能只做一些其他的实现。无论如何,好处是使用已知的模式,并且您有一个词来描述实现。通常,这在与团队合作时很重要,因为这样您就可以有效地描述实现细节。(当其他开发人员也知道模式时)

当您使用自己的方法来实现行为时,通常需要一些时间来讨论它是如何工作的。

第二个好处是装饰图案试图解决的问题。装饰图案-维基百科

  • 职责应该在运行时动态地添加到对象(并从中删除)。
  • 应提供扩展功能的灵活的子类化替代方案。

我之所以提到这一点,是因为使用模式在处理遗留代码/未知代码时非常有用。通常,您需要这种技巧来添加新的行为,而不修改原始实现。