Decorator方法,Java中的一个Decorator类型

我正在学习使用装饰模式,我遇到了一个我认为很简单的问题,但我似乎无法找到答案。 假设我有一个抽象的饮料类。 然后,假设我有几个延伸饮料的具体组件:americano,espresso,latte等。还有一个抽象的调味品类扩展了饮料。 调味品类然后有多个小类:牛奶,糖,大豆,鞭子。 每个调味品子类都有一个分别从Beverage和Condiments继承的cost和getdescription()方法。 我的问题是,在测试时,如何阻止某个具有多种同类型调味品的饮料实例,例如,即使大豆在测试课程中陈述了两次,也只能收取一次大豆。 我知道我可以将调味品保存到列表中,并在添加新调味品时检查是否存在调味品,我只想看看是否有更好的选择。

饮料类

public abstract class Beverage {

    String description = "Unknown Beverage";

    public String getDescription() {
        return description;
    }

    public abstract double cost();

}

调味品装饰者

public abstract class CondimentDecorator extends Beverage {

    public abstract String getDescription();

}

DarkRoast类

public class DarkRoast extends Beverage {

    public DarkRoast() {
        description = "Dark Roast Coffee";
    }

    public double cost() {
        return .99;
    }

}

大豆类

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

}

如果有人能够帮助,甚至指向我一篇好文章或教程,我将不胜感激。


听起来就像Head First Design Patterns(HFDP)的例子? 该测试案例很容易理解,但要做的事情可能并不多。

将装饰者想象成包装。 当装饰器要包装某些东西时,它可以检查“东西”是否已经包含它自己类型的装饰器。 这里是我轻微改变的HFDP代码:

Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Soy(beverage2);     // wrap once
beverage2 = new Soy(beverage2);     // wrap again (**error case)

您必须决定是否禁止所有装饰器的多个包装,或者某些装饰器可能有一种“仅一次”属性。 另一个要决定的是,如果发生第二次换行(上面注释中的**),或者您想忽略cost()的额外换行,是否失败(抛出异常cost()

如果你在包装时停止多个包装,它可能更干净,更不容易出错。 这将在构造函数中。 你可以在抽象类中编写一个通用函数,它使用反射来检查它(不支持不支持它的语言),或者解析被包装对象的描述以找到它自己的字符串(如果装饰不够可靠,没有独特的名字)。

我在做这件事时看到的最大问题是调味品包装饮料,并且通过设计(信息隐藏),调味品不会“知道”他们正在包装其他调味品。 你写的任何代码都可能是脆弱的(它可能违反了开闭原则)。 然而,这是设计中的折衷。 你不能拥有所有东西,所以决定什么更重要(停止多个包装,或者有一个允许添加新装饰器而不破坏任何东西的设计)。

使用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”并为其编码。

链接地址: http://www.djcxy.com/p/32005.html

上一篇: Decorator method, one Decorator type in Java

下一篇: Observer pattern used with decorator pattern