这里真的需要装饰器模式吗?

时间:2019-01-21 06:25:00

标签: java design-patterns

我正在从Head First设计模式书中学习装饰器设计模式。他们的示例将不同类型的咖啡视为饮料。饮料以牛奶,大豆,鲜奶油等为装饰。例如,带有摩卡咖啡和鲜奶油的DarkRoast咖啡: decorator example

类图: class diagram

我了解到使用此示例仅是因为它很简单。但是,我有另一种更简单的方法来实现没有装饰器模式的此示例。我们可以有一个带有描述和成本的Item类。然后,饮料类可以具有baseCost,totalCost和项目列表。

与装饰器图案相比,这种替代设计是否有主要缺点?您能否提供装饰器模式比我的设计更好的任何特定方案?

PS-万一有人想看到装饰代码:https://github.com/bethrobson/Head-First-Design-Patterns/tree/master/src/headfirst/designpatterns/decorator/starbuzz

3 个答案:

答案 0 :(得分:1)

example主要关于如何使用装饰器模式

  

模式可能是一个复杂的主题,与如何使用

相比,知道何时使用它们有时会更加复杂。

将其他examples称为Mat,在其中您向对象添加功能,例如颜色:

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 + ")";
   } 

这是使用装饰器模式,添加功能而无需多重继承的主要原因

  

与静态(多个)继承相比,装饰器模式提供了一种更加灵活的向对象添加职责的方式

答案 1 :(得分:0)

基本上,一种特定的饮料由成分的链接列表表示。 getDescription()方法以递归方式构建饮料的字符串表示形式。

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

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

您可以通过考虑管理另一个数据结构的开销(而不是链表的简单性)来决定哪种解决方案更好,请记住,如果链表中有很多项,尤其是在您需要随机访问的情况下,链表可能会很昂贵访问元素。示例:您需要O(n)循环(其中n是列表大小)来检查饮料是否具有给定的成分,而哈希表的作用要小得多。但是对于低n值,使用哈希表的解决方案可能会更慢,因为它是一个更复杂的数据结构。

您问题的答案取决于具体情况,但总的来说,另一种方法没有错。

答案 2 :(得分:-1)

在该示例中,没有装饰器模式也可能具有相同的行为。我同意其他人已经说过的话。当然,该示例仅用于学习如何与装饰器一起工作并识别图案。

我想在这里补充一点我如何看待该问题。 (因为您说过您正在学习模式)

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

当您使用自己的方式来实现该行为时,通常需要花费一些时间来讨论其工作方式。

第二个好处是装饰器模式试图解决的问题。 Decorator Pattern - Wikipedia

  • 应在运行时动态将责任添加到对象(或从对象中删除)。
  • 应该提供一种灵活的替代子类的扩展功能。

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