java - 如何使用装饰器 DP 将 addDough 方法写入我的披萨

标签 java oop design-patterns decorator

我正在制作三种类型的披萨(鸡肉、意大利辣香肠和素食),每种披萨都可以有额外的配料,这会增加披萨的价格(比如额外的奶酪、香肠......),所以我知道我需要使用装饰师 DP 但我的问题是我有 2 种面团(扁面包和薄皮),我的每个披萨都应该有一个面团,但我不知道在哪里添加面团部分。 这是我的披萨界面:

public interface Pizza {
    public String getDescription();
    public double getCost();    
 }

这是我的鸡肉披萨类(class)(稍后添加意大利辣香肠和蔬菜):

public class ChickenPizza implements Pizza {

    @Override
    public String getDescription() {

        return "Chicken";
    }
    @Override
    public double getCost() {

        return 10;
    }
}

我的 ToppingDecorator 类:

public abstract class ToppingDecorator implements Pizza {
    protected Pizza tempPizza;
    public ToppingDecorator(Pizza newPizza) {
        tempPizza=newPizza;
    }

    @Override
    public String getDescription() {
        return tempPizza.getDescription();
    }

    @Override
    public double getCost() {
        return tempPizza.getCost();
    }
}

还有我的ExtraCheese类(class)(稍后将添加香肠和其他配料):

public class ExtraCheese extends ToppingDecorator{

    public ExtraCheese(Pizza newPizza) {
        super(newPizza);
    }


    public String getDescription() {
        return tempPizza.getDescription()+", Extra Cheese";
    }


    public double getCost() {
        return tempPizza.getCost()+2;
    }
}

所以我的问题是:一开始我认为我应该为扁面包面团制作 2 类,另一类为薄皮面团(就像我对额外奶酪所做的那样),但这不会改变成本,然后我认为我应该在 Pizza 接口(interface)中创建一个抽象的 get 和 set 方法,但我不确定。

最佳答案

我们可以通过多种方式实现装饰模式,用额外的成分来装饰对象。我们先来看看描述什么是decorator :

  • 动态地将附加职责附加到对象。 装饰器为子类化提供了灵活的替代方案 扩展功能。
  • 客户端指定的递归修饰核心对象 包裹它。
  • 包装礼物,将其放入盒子中,然后包装盒子。

正如您所看到的,上述限制很广泛,我们有一定的灵 active 。我们可以像考虑配料表一样考虑披萨。我们可以选择面团、蔬菜等。我们也可以将披萨类作为配料。当然,我们可以创建两种模型层次结构:一种用于所有比萨饼,另一种用于所有其他成分,但一个层次结构应该足够了。此外,对于预定义的成分,我们可以创建新类或仅创建灵活的构造函数,这允许我们根据需要动态创建尽可能多的成分。您可以使用 builder 轻松绑定(bind)装饰器模式或/和abstract factory .

下面的示例显示了带有构建器模式的简单装饰器,用于构建具有预定义成分和额外愿望的披萨:

import java.math.BigDecimal;

public class DesignPatterns {

    public static void main(String[] args) {
        Ingredient chicken = new PizzaBuilder().chicken()
                .withFlatBread()
                .withSausage()
                .build();
        System.out.println(chicken);

        Ingredient pepperoni = new PizzaBuilder().pepperoni()
                .withThinCrust()
                .withSausage()
                .withExtraCheese()
                .build();
        System.out.println(pepperoni);

        Ingredient vegetarian = new PizzaBuilder().vegetarian()
                .withCustomerWish("Mushrooms", BigDecimal.ONE)
                .build();
        System.out.println(vegetarian);
    }
}

class FlatBread extends Ingredient {

    public FlatBread(Ingredient pizza) {
        super(pizza, "Flat bread", new BigDecimal("0.25"));
    }
}

class ThinCrust extends Ingredient {
    public ThinCrust(Ingredient pizza) {
        super(pizza, "Thin Crust", new BigDecimal("0.50"));
    }
}

class ChickenPizza extends Ingredient {

    public ChickenPizza() {
        super("Chicken", new BigDecimal("3.25"));
    }
}

class Pepperoni extends Ingredient {

    public Pepperoni() {
        super("Pepperoni", new BigDecimal("4.50"));
    }
}

class Ingredient {

    private final Ingredient base;
    private final String name;
    private final BigDecimal price;

    public Ingredient(String name, BigDecimal price) {
        this(null, name, price);
    }

    public Ingredient(Ingredient base, String name, BigDecimal price) {
        this.name = name;
        this.price = price;
        this.base = base;
    }

    public String getName() {
        if (base != null) {
            return base.getName() + ", " + name;
        }

        return name;
    }

    public BigDecimal getPrice() {
        if (base != null) {
            return price.add(base.getPrice());
        }

        return price;
    }

    @Override
    public String toString() {
        return '\'' + getName() + "' costs = " + getPrice() + " $";
    }
}

class PizzaBuilder {

    IngredientsBuilder chicken() {
        return new IngredientsBuilder(new ChickenPizza());
    }

    IngredientsBuilder pepperoni() {
        return new IngredientsBuilder(new Pepperoni());
    }

    IngredientsBuilder vegetarian() {
        return new IngredientsBuilder(new Ingredient("Vegetarian", new BigDecimal("2.89")));
    }

    // other pizza types

    class IngredientsBuilder {

        private Ingredient instance;

        private IngredientsBuilder(Ingredient pizza) {
            this.instance = pizza;
        }

        IngredientsBuilder withFlatBread() {
            instance = new FlatBread(instance);
            return this;
        }

        IngredientsBuilder withThinCrust() {
            instance = new ThinCrust(instance);
            return this;
        }

        IngredientsBuilder withSausage() {
            instance = new Ingredient(instance, "Sausage", new BigDecimal("0.49"));
            return this;
        }

        IngredientsBuilder withExtraCheese() {
            instance = new Ingredient(instance, "Extra cheese", new BigDecimal("0.56"));
            return this;
        }

        IngredientsBuilder withCustomerWish(String name, BigDecimal price) {
            instance = new Ingredient(instance, name, price);
            return this;
        }

        // other ingredients

        Ingredient build() {
            return instance;
        }
    }
}

上面的代码打印:

'Chicken, Flat bread, Sausage' costs = 3.99 $
'Pepperoni, Thin Crust, Sausage, Extra cheese' costs = 6.05 $
'Vegetarian, Mushrooms' costs = 3.89 $

关于java - 如何使用装饰器 DP 将 addDough 方法写入我的披萨,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55689808/

相关文章:

java - Java 10 中的 "var"到底是什么类型的 token ?

java - 如何对迭代器中的 getter 方法的值求和?

java - 策略模式的鸭子示例

design-patterns - 避免将 boolean 标志作为属性

java - 无法运行 .jar 文件/java.jar : line 1: public: command not found

java - 当子类中使用字 "super"时,字 super 强制代码做什么?

java - Java 方法参数可以是声明大小的集合吗?

javascript - 如何在 React App 中为组件实现工厂模式?

java - 为什么 String.equals 对于不相同(但相等)的 String 对象要慢得多?

java - 为什么 SocketChannel 是抽象的?