在书中'Head first design patterns',装饰器章节,它讨论了装饰器处理具体类型并导致问题时的问题。我正在复制章节中的一些问答:
问:我有点担心代码可能会测试一个特定的具体组件 - 比如HouseBlend--并做一些事情,比如发一个折扣。一旦我用装饰器包装HouseBlend,这就不再适用了。答:这是完全正确的。如果您的代码依赖于具体组件的类型,装饰器将破坏该代码。只要您只针对抽象组件类型编写代码,装饰器的使用将对您的代码保持透明。但是,一旦开始编写针对具体组件的代码,您将需要重新考虑应用程序设计和装饰器的使用。
有人可以提供简单的例子,说明'客户'代码是针对具体类型与抽象类型编写的吗?前者如何给装饰者带来麻烦?
书中装饰器的示例测试代码如下:
public class StarbuzzCoffee {
public static void main(String args[]) {
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription()
+ “ $” + beverage2.cost());
...
}
}
此测试代码(也是客户端代码)是否针对抽象类型编写?
谢谢,
答案 0 :(得分:2)
他们谈论的是检查饮料2类型的代码,例如
if (beverage2 instanceof DarkRoast) {
<do_something>
}
用摩卡或鞭子装饰drink2后,它就不再是DarkRoast了。
编辑:我还应该提一下,instanceof
的使用常常表明设计不合理,不能充分利用OO,并表示在某些情况下它很有用。
答案 1 :(得分:0)
只要您只针对抽象组件类型编写代码,装饰器的使用将对您的代码保持透明
是。它应该是这样的。
您不应该修饰特定于具体装饰器实现的新功能。一旦你这样做,装饰模式的目的就会丢失。
由于抽象的Decorator包含接口本身(使用合成),装饰器模式很有效。它有助于减少不同口味的不同组合的数量。
我已经为类似的用例实现了Decorator模式。请查看此文档链接
When to Use the Decorator Pattern?
Beverage beverage = new SugarDecorator(new LemonDecorator(new Tea("Assam Tea")));
beverage.buildBeverage();
输出为18,即Tea (10) + Lemon (5) + Sugar (3)
:
Cost of:Assam Tea+Lemon +Sugar :18
要使上述示例正常工作,您需要对摘要Decorator
进行一些更改,如文档链接中所述。由于Beverage
抽象类中Decorator
的组合,可以轻松添加多种风格。
您永远不应该根据Concrete Decorator添加业务逻辑 。如果您在代码中加入了Concrete Decorator的智能,则会失去独立添加动态职责的灵活性。