Decorator method, one Decorator type in Java
我在学习使用装饰图案的过程中,遇到了一个我认为很简单但似乎找不到答案的问题。假设我有一个抽象的饮料类。那么让我们假设我有一些扩展饮料的具体成分:美式咖啡、浓缩咖啡、拿铁等等,还有一种抽象的调味品类扩展饮料。然后调味品类有多个子类:牛奶、糖、大豆、鞭子。每个调味品子类都有一个分别从饮料和调味品继承的cost和getdescription()方法。我的问题是,在测试时,我如何阻止某个饮料实例使用同一类型的多种调味品,也就是说,美国的大豆只需收费一次,即使大豆在测试课上说了两次。我知道我可以将调味品保存到一个列表中,并在添加新的调味品时检查它是否存在,我只是想看看是否存在更好的选择。
饮料类
1 2 3 4 5 6 7 8 9 10 11 |
调味品装饰师
1 2 3 4 5 | public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); } |
暗黑类
1 2 3 4 5 6 7 8 9 10 11 | public class DarkRoast extends Beverage { public DarkRoast() { description ="Dark Roast Coffee"; } public double cost() { return .99; } } |
大豆类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Soy extends CondimentDecorator { Beverage beverage; public Soy(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() +", Soy"; } public double cost() { return .15 + beverage.cost(); } } |
如果有人能帮助我,甚至给我指一篇好文章或一个教程,我会非常感谢。
听起来像头一设计模式(HFDP)的例子?测试用例很容易理解,但是方法可能不太多。
把装修工想象成包装工。当一个装饰器要包装某个东西时,它可以检查那个"东西"是否已经包含了它自己类型的装饰器。以下是我稍微修改过的HFDP代码:
1 2 3 4 | Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Soy(beverage2); // wrap once beverage2 = new Soy(beverage2); // wrap again (**error case) |
您必须决定是否要禁止所有装饰器使用多个包装,或者某些装饰器可能具有一种"仅一次"属性。另一件要决定的事情是,如果发生第二次换行(上面注释中的**),是否失败(抛出异常),或者您只想忽略EDOCX1中的额外换行(0)。
如果您在包装时停止多次包装,它可能更干净,更不容易出现错误。在构造函数中。您可以在抽象类中编写一个通用函数,该函数使用反射(在不支持反射的语言中不起作用),或者解析被包装对象的描述以找到它自己的字符串(如果装饰没有唯一的名称,则不太可靠)。
我看到的最大的问题是调味品包装饮料,而且根据设计(信息隐藏),调味品不"知道"他们包装其他调味品。您编写的任何代码都可能是脆弱的(它可能违反开放-关闭原则)。然而,这就是设计上的权衡。你不能拥有所有东西,所以决定什么更重要(停止多重包装,或者设计一个允许添加新的装饰而不破坏任何东西)。
如果您可以依赖格式来标识嵌套,那么使用getdescription(解析它)可能是最有意义的。
大豆类可以做到这一点:
1 2 3 4 5 6 7 |
但更好的方法可能是在","字符上使用
如我所说,如果禁止所有多个调味品包装是一个一般规则,那么您可以将此逻辑重构为ConditionTDecorator类,以避免代码重复。甚至可以使用decorator-boolean属性来表示"allowmultiple"并对其进行编码。