【发布时间】:2017-09-19 19:12:10
【问题描述】:
“Head First: Design Patterns”一书中的装饰器模式用例让我产生了这个问题。我会试着写下来:
这是一个咖啡店系统,有一些咖啡和很多调味品 你可以把它们放进去(额外收费),你需要能够订购 并收取客户想要的任何调味品的咖啡,以及 以避免完全混乱(例如布尔值来跟踪 调味品)使用装饰图案。我们有一个抽象的饮料 类,每种类型的咖啡作为具体成分和每种调味品 作为包装饮料的混凝土装饰师,像这样:
因此我们有以下流程返回咖啡成本:
我的问题是:为什么不用列表而不是装饰器来实现呢?我们可以在每个饮料中有一个调味品列表,并通过遍历列表来计算成本。要订购咖啡,我们只需要实例化一次并添加所需的调味品,避免以下声明:
// Using second image example
Beverage beverage = new DarkRoast(beverage);
beverage = new Mocha(beverage);
beverage = new Whip(beverage);
除此之外,我们将在操作方面拥有更大的灵活性,例如为不包括调味品的咖啡提供折扣,一旦我们没有装饰员来包装咖啡。这是一个长期研究的问题,我知道我遗漏了一些东西或者我做错了什么,所以如果你对此有任何想法,我很想知道并进一步讨论。
【问题讨论】:
-
这与您必须按成本减去或增加的折扣或税费清单无关。这是关于您使用装饰器模式处理的行为。而且,相信我,使用列表而不是继承来处理这些行为更难。
-
你能举个例子吗?或者可能是另一个随机案例?我真的无法想象会发生这种情况。
-
这似乎是一个更适合softwareengineering.stackexchange.com 的问题。就我个人而言,我认为这是对装饰器的糟糕使用(我认为维基百科也有这样的例子)并且绝对可以通过更易于管理的方式通过列表来解决。
java.io.InputStream是一个很好用的装饰器示例。但是,您已经可以看到有一个用户不同意我的观点,这就是为什么这可能与 SO 无关。 -
这是一个非常人为的例子。书本练习经常是。你的直觉很好,这表明你理解了这个例子。使用继承来模拟调味品对我来说是一种反模式,但作为一个易于获取的示例,它可以工作。在现实生活中,我也会使用列表。当您增强现有对象的行为时,最好使用装饰器模式。例如将哈希映射组合在一起或将默认值添加到哈希映射。
-
InputStream 很好,因为您正在用更高级别的抽象包装一个较低级别的源代码。您从字节数组、URL、文件等源开始,然后说“忘记那个。现在我只想从中获取对象”并将其包装在 ObjectInputStream 中。使用 InputStream,您实际上希望或多或少地忘记您正在装饰的对象。以饮料为例,在某些时候您将需要例如迭代所有的成分,然后把它们放在一个表什么的,然后装饰器只是一个笨重的链表。
标签: java list oop design-patterns decorator