我正在从Head First设计模式书中学习装饰器设计模式。他们的示例将不同类型的咖啡视为饮料。饮料以牛奶,大豆,鲜奶油等为装饰。例如,带有摩卡咖啡和鲜奶油的DarkRoast咖啡:
我了解到使用此示例仅是因为它很简单。但是,我有另一种更简单的方法来实现没有装饰器模式的此示例。我们可以有一个带有描述和成本的Item类。然后,饮料类可以具有baseCost,totalCost和项目列表。
与装饰器图案相比,这种替代设计是否有主要缺点?您能否提供装饰器模式比我的设计更好的任何特定方案?
PS-万一有人想看到装饰代码:https://github.com/bethrobson/Head-First-Design-Patterns/tree/master/src/headfirst/designpatterns/decorator/starbuzz
答案 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
之所以提及这一点,是因为在处理遗留代码/未知代码时,使用模式非常有用。通常,那么您需要那种技巧来添加新行为,而无需修改原始实现。