当前位置: 首页 > 面试题库 >

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

祁渊
2023-03-14
问题内容

我正在学习使用装饰器模式,但遇到一个我认为很简单但似乎找不到答案的问题。假设我有一个抽象的饮料类。然后,让我们说一下扩展饮料的一些具体组成部分:美式咖啡,浓缩咖啡,拿铁咖啡等。还有扩展饮料的抽象调味品类。然后,调味品类有多个子类:牛奶,糖,大豆,鞭子。每个调味品子类都有一个cost和getdescription()方法,分别从Beverage和Condiments继承。我的问题是,如何在测试时停止某个饮料实例具有多个与之相关的相同类型的调味品,即美国人仅一次向大豆收费,即使大豆在测试班中两次被指控也是如此。

饮料类

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

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

我看到的最大问题是调味品包裹了饮料,而根据设计(信息隐藏),调味品并不“知道”它们在包裹其他调味品。您编写的任何代码都可能是易碎的(可能违反了开闭原则)。但是,这是设计的权衡。您无法拥有所有内容,因此请确定更重要的内容(停止多次包装,或设计允许添加新装饰器而不破坏任何内容)。

使用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”并进行编码。



 类似资料:
  • 我正在学习使用decorator模式,我遇到了一个问题,我认为这个问题很简单,但我似乎找不到答案。假设我有一个饮料课是抽象的。然后让我们假设我有几个具体的成分延伸饮料:美式咖啡,浓缩咖啡,拿铁等等,还有一个抽象的调味品类延伸饮料。调味品类又有多个子类:牛奶、糖、大豆、鞭。每个调味品子类都有一个cost和getdescription()方法,分别继承自Beverage和addinments。我的问题

  • 装饰器模式允许用户在不改变其结构的情况下向现有对象添加新功能。 这种类型的设计模式属于结构模式,因为此模式充当现有类的包装器。 此模式创建一个装饰器类,它包装原始类并提供其他功能,使类方法签名保持不变。 装饰器模式的动机是动态附加对象的附加职责。 如何实现装饰设计模式 下面提到的代码是如何在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