当前位置: 首页 > 知识库问答 >
问题:

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

徐鸿达
2023-03-14

我正在学习使用decorator模式,我遇到了一个问题,我认为这个问题很简单,但我似乎找不到答案。假设我有一个饮料课是抽象的。然后让我们假设我有几个具体的成分延伸饮料:美式咖啡,浓缩咖啡,拿铁等等,还有一个抽象的调味品类延伸饮料。调味品类又有多个子类:牛奶、糖、大豆、鞭。每个调味品子类都有一个cost和getdescription()方法,分别继承自Beverage和addinments。我的问题是,当测试时,我如何阻止某个饮料实例有一种以上的同类型调味品与之相关联,即一个美国人只对大豆收取一次费用,即使大豆在测试类中被声明了两次。我知道我可以保存一个调味品到一个列表,并检查它是否存在时,添加一个新的调味品,我只是想看看是否有一个更好的选项存在。

饮料类

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

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

}

如果有人能帮助我,甚至指出一个好的文章或教程,我将非常感谢。

共有1个答案

养振濂
2023-03-14

听起来像头优先设计模式(HFDP)的例子?测试用例理解起来很简单,但做的方法可能没有那么多。

把装潢者看成包装者。当装饰器要包装某个东西时,它可以检查那个“东西”,看看它是否已经包含了它自己类型的装饰器。以下是我对HFDP的代码进行了轻微修改:

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

您必须决定是否不允许对所有装饰器进行多重包装,或者某些装饰器可以有一种“Once Only”属性。另一个需要决定的问题是,如果发生第二次包装(上面注释中的**),或者您想忽略cost()中的额外包装,是失败(抛出异常)。

如果您在包装时停止多次包装,可能会更干净,也不容易出现bug。在构造函数中。您可以在抽象类中编写一个通用函数,该函数使用反射进行检查(在不支持反射的语言中不起作用),或者解析包装对象的描述以找到它自己的字符串(如果装饰没有唯一的名称,则不太可靠)。

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

使用getDescription(解析它)可能是最有意义的,前提是您可以依赖格式来标识嵌套。

Soy类可以这样做:

private String myDescription = "Soy"
public Soy(Beverage beverage) {
    if (beverage.getDescription().contains(myDescription)) {
        throw new Exception();
}
    this.beverage = beverage;
}

但更好的方法可能是在“,”字符上使用.split()并检查这些字符串,因为描述只是使用逗号(在getDescription()中)的串联。

正如我所说的,如果不允许所有多个调味品包装是一个一般规则,那么您可以将此逻辑重构到ConditmentDecorator类,以避免重复代码。您甚至可以使用Decorator boolean属性来表示“allowsmultiple”并对其进行编码。

 类似资料:
  • 问题内容: 我正在学习使用装饰器模式,但遇到一个我认为很简单但似乎找不到答案的问题。假设我有一个抽象的饮料类。然后,让我们说一下扩展饮料的一些具体组成部分:美式咖啡,浓缩咖啡,拿铁咖啡等。还有扩展饮料的抽象调味品类。然后,调味品类有多个子类:牛奶,糖,大豆,鞭子。每个调味品子类都有一个cost和getdescription()方法,分别从Beverage和Condiments继承。我的问题是,如何

  • 装饰器模式允许用户在不改变其结构的情况下向现有对象添加新功能。 这种类型的设计模式属于结构模式,因为此模式充当现有类的包装器。 此模式创建一个装饰器类,它包装原始类并提供其他功能,使类方法签名保持不变。 装饰器模式的动机是动态附加对象的附加职责。 如何实现装饰设计模式 下面提到的代码是如何在Python中实现装饰器设计模式的简单演示。 插图包括以课堂形式演示咖啡店。 创建的咖啡类是抽象的,这意味着

  • Webpage Decorator 这个Chrome浏览器扩展提供了一些可以自定义网页颜色主题和字体的选项。不过安装本扩展后会在Chrome浏览器的地址栏右侧增加一个按钮,也许这会 导致部分网页的地址显示不全。 单击这个按钮就会打开此扩展的选项,可以调整网页背景图片、背景颜色、已读链接的颜色以及网页文字的颜色、字体大小和字体类型等。 颜色选择器是为改变颜色准备的,使用者通过它可选择自己喜欢的颜色或

  • Apollo Storybook Decorator Wrap your React Storybook stories with Apollo Client. Supports React React Native Vue Angular Apollo Client V2 Coming Soon Apollo Client V1 X X X The Gist Provide GraphQL ty

  • 问题内容: 为什么不能修饰静态方法或类方法? 双方并导致。 为什么依赖属性而不是属性?(Afaik的所有函数(包括类方法和静态方法)都具有该属性。) 编辑:我正在使用Python 2.6。 问题答案: 当和是最高的装饰器时,它起作用:

  • ember-cached-decorator-polyfill Polyfill for RFC 566 "@cached decorator". Installation ember install ember-cached-decorator-polyfill For addons, pass the -S flag. Compatibility Ember.js v3.13 or above