【问题标题】:Which design pattern to use for making Pizza制作披萨使用哪种设计模式
【发布时间】:2015-09-26 16:14:16
【问题描述】:

我想做一个小应用程序,它会根据给定的输入返回一个比萨饼。 我想用不同的投入制作一个中等大小的披萨 1. 像白色面团或棕色面团 2. 不同类型的奶酪配料,例如白色或棕色奶酪 3. 洋葱或番茄或蘑菇的不同配料

那么我们如何决定在这里选择哪种模式,Builder 还是 Decorator? 我觉得我们可以先使用构建器模式制作披萨,然后我们可以使用装饰器模式并根据我们选择的不同浇头装饰披萨。我的理解是否正确? 据我了解,装饰器模式用于装饰任何已经存在的对象。要创建这个现有对象,我们将首先使用构建器模式。

【问题讨论】:

  • 设计模式是针对编程语言不足的变通方法,那么您使用的是哪种语言呢?
  • 用户是厨师还是顾客?
  • 你还需要一个高效的设计模式来吃它:strauss.za.com/sla/sla_pizza.asp (SCNR)
  • 我正在使用 Java,我是这里的客户。我觉得可以使用构建器模式,因为可以根据披萨类型更改成分。

标签: design-patterns


【解决方案1】:

创意模式不是你想要的:你只有一种类型的对象:比萨。所以工厂模式和建造者模式都行不通。

根据维基百科:

Decorator 模式允许用户将新功能添加到 现有对象而不改变其结构。这种设计 模式属于结构模式,因为这种模式充当 包装到现有的类。

装饰器模式显然是您所需要的。

【讨论】:

  • 没有。装饰器模式添加了功能,这是真的,但披萨的工作方式相同,无论是洋葱还是洋葱,都不需要额外的功能。
  • 我不同意。 “成分”“功能”。
  • 我对如何通过比萨示例实现这一点非常感兴趣。您可以通过添加一个 java 示例来更新您的答案吗?
  • 来自 Wikipedia:Decorator_pattern: ...“每次向被覆盖的方法添加新功能...”在我的理解中,wiki 文章范围内的功能意味着“方法”!
  • 我同意使用装饰器。您基本上可以将那些 setX 抽象为 setIngredient()。从本质上讲,您可以用无限数量的食材来装饰“披萨”,而永远不要更改涉及披萨代码的任何内容。
【解决方案2】:

所有示例都是用 Java 编写的

TLTR:向下滚动到 Builder 模式

装饰器模式(在这种情况下不要使用它)

如果你有一个代表矩形的类,就会使用装饰器模式。 Rectangle 类只有一种计算周长的方法。现在您想向 Rectangle 添加一个方法来计算面积。问题是您不能也不想编辑 Rectangle 类,因此您创建了一个新类 MySuperDuperRectangle,例如:

外围界面:

interface Perimeter{
    public int perimeter();
}

由于某种原因我们无法更改的矩形

class Rectange implements perimeter{
    private int a, b;

    public Rectange(int a, int b){
        this.a = a;
        this.b = b;
    }

    public int getA(){
        return a;
    }
    public int getB(){
        return b;
    }

    public int perimeter(){
        return 2 * a + 2 * b;
    }

}

装饰的矩形:

class MySuperDuperRectange implements perimeter{
    private Rectange r;

    public MySuperDuperRectange(Rectange r){
        this.r = r;
    }

    public int perimeter(){
        return r.perimeter();
    }

    public float area(){
        return r.getA() * r.getB();
    }

}

Builder 模式(我会在这种情况下使用它)

我会使用 Builder 模式,因为任务是 building 披萨。

Builder 模式用于构建后缀按原样存在的东西(并且在任何时候都不应更改)。

PizzaBuiler 的基本实现如下所示:

面团枚举:

enum Dough{
    WHITE, BROWN
}

奶酪枚举:

enum Cheese{
    WHITE, BROWN
}

浇头枚举:

enum Topping{
    Kittens, Onions, Salami
}

美味比萨:

class Pizza{

    private Dough dough;
    private Cheese cheese;
    private HashSet<Topping> toppings;

    private Pizza(Dough dough, Cheese cheese, HashSet<Topping> toppings){
        this.dough = dough;
        this.cheese = cheese;
        this.toppings = toppings;
    }

    //add some getters

}

PizzaBuilder:

class PizzaBuilder{

    private Dough dough;
    private Cheese cheese;
    private HashSet<Topping> toppings = new HashSet<Topping>();

    public PizzaBuilder(){

    }
    public PizzaBuilder setDough(Dough dough){
        this.dough = dough;
        return this;
    }
    public PizzaBuilder setCheese(Cheese cheese){
        this.cheese = cheese;
        return this;
    }
    public PizzaBuilder addTopping(Topping topping){
        this.toppings.add(topping);
        return this;
    }
    public Pizza buildPizza(){
        return new Pizza(this.dough, this.cheese, this.toppings);
    }

}

现在我们要制作披萨了:

Pizza myPizza = new PizzaBuilder()
        .setDough(Dough.WHITE)
        .setCheese(Cheese.WHITE)
        .addTopping(Topping.Kittens)
        .addTopping(Topping.Salami)
        .buildPizza();

正如你所见,创建一个新的比萨是非常困难的,不需要你为地球上所有可能的比萨编写一个新类;)

参考实现:Builder Pattern

【讨论】:

    【解决方案3】:

    在构建披萨对象时,您可以继续使用 Builder 模式、传递面团、您选择的配料,这里不需要装饰器模式:

    建造者模式的例子,像这样:

    package com.builder.pattern;
    

    公开课披萨{

    boolean isCheesy;
    boolean isTomato;
    boolean isMaxican;
    
    public Pizza(PizzaBuilder pizzaBuilder) {
        this.isCheesy = pizzaBuilder.isCheesy;
        this.isTomato = pizzaBuilder.isTomato;
        this.isMaxican = pizzaBuilder.isMaxican;
    }
    
    static class PizzaBuilder {
    
        boolean isCheesy;
        boolean isTomato;
        boolean isMaxican;
    
        public Pizza build() {
            return new Pizza(this);
        }
    
        public PizzaBuilder setCheese(boolean isCheesy) {
            this.isCheesy = isCheesy;
            return this;
        }
    
        public PizzaBuilder setTomato(boolean isTomato) {
            this.isTomato = isTomato;
            return this;
        }
    
        public PizzaBuilder setMaxican(boolean isMaxican) {
            this.isMaxican = isMaxican;
            return this;
        }
    }
    
    @Override
    public String toString() {
        return "Pizza [isCheesy=" + isCheesy + ", isTomato=" + isTomato + ", isMaxican=" + isMaxican + "]";
    }
    

    }

    准备披萨如下:

    Pizza pizza = new Pizza.PizzaBuilder().setCheese(false).setTomato(true).setMaxican(true).build();
        System.out.println(pizza);
    

    或者像这样

    Pizza pizza = new Pizza.PizzaBuilder().setMaxican(true).build();
    System.out.println(pizza);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多