装饰设计模式问题?

时间:2012-09-28 06:01:44

标签: oop design-patterns decorator

在书中'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());
        ...
    }
}

此测试代码(也是客户端代码)是否针对抽象类型编写?

谢谢,

2 个答案:

答案 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的智能,则会失去独立添加动态职责的灵活性。