3

《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());
        ...
    }
}

这个测试代码(也是客户端代码)是针对抽象类型编写的吗?

谢谢,

4

2 回答 2

3

例如,他们正在谈论检查饮料2类型的代码

if (beverage2 instanceof DarkRoast) {
    <do_something>
}

一旦你用摩卡或鞭子装饰饮料2,它就不再是 DarkRoast。

编辑:我还应该提到,通常使用instanceof表示没有充分使用 OO 的糟糕设计,这表示它在某些情况下很有用。

于 2012-09-28T06:11:00.723 回答
0

只要您只针对抽象组件类型编写代码,装饰器的使用将对您的代码保持透明

是的。这就是它应该的方式。

您不应该装饰特定于具体装饰器实现的新功能。一旦你这样做了,装饰器模式的目的就失去了。

由于包含接口本身的抽象装饰器(使用组合),装饰器模式运行良好。它有助于减少不同口味的不同组合的数量。

我已经 为类似的用例实现了装饰器模式。看看这个文档链接

何时使用装饰器模式?

 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如文档链接中所述。由于抽象类的组成BeverageDecorator可以很容易地添加多种口味。

你永远不应该基于 Concrete Decorator 添加业务逻辑。如果你在代码中加入了 Concrete Decorator 的智能,你就会失去独立添加动态职责的灵活性。

于 2016-08-04T15:32:27.493 回答