小编典典
将装饰者视为包装器。当装饰器将要包装东西时,它可以检查“事物”以查看其是否已经包含自己类型的装饰器。这是HFDP的代码,我做了一些改动:
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Soy(beverage2); // wrap once
beverage2 = new Soy(beverage2); // wrap again (**error case)
您必须决定是否要禁止所有装饰器多重包装,或者某些装饰器可以具有“仅一次”属性。要决定的另一件事是,是否发生第二次换行(上述注释中的**)是否失败(引发异常),或者是否只想忽略中的多余换行cost()。
如果您在包装时停止多次包装,则可能更清洁,而且更不易出错。那将在构造函数中。您可以在抽象类中编写一个通用函数,该通用函数使用反射进行检查(在不支持该反射的语言中不起作用),或者解析包装对象的描述以找到自己的字符串(如果装饰不可靠,则不太可靠)
t具有唯一的名称)。
我看到的最大问题是调味品包裹了饮料,而根据设计(信息隐藏),调味品并不“知道”它们在包裹其他调味品。您编写的任何代码都可能是易碎的(可能违反了开闭原则)。但是,这是设计的权衡。您无法拥有所有内容,因此请确定更重要的内容(停止多次包装,或设计允许添加新装饰器而不破坏任何内容)。
使用getDescription(解析它)可能最有意义,前提是您可以依靠格式来识别嵌套。
大豆课可以做到这一点:
private String myDescription = "Soy"
public Soy(Beverage beverage) {
if (beverage.getDescription().contains(myDescription)) {
throw new Exception();
}
this.beverage = beverage;
}
但是更好的方法可能是.split()使用“,”字符并检查那些字符串,因为描述只是使用逗号(在中getDescription())的串联。
正如我所说,如果禁止所有调味品包装是一条通用规则,则可以将此逻辑重构到CondimentDecorator类,以避免重复代码。您甚至可以让Decorator布尔值属性说“
allowsMultiple”并进行编码。
2020-11-01