披萨店小程序_比萨问题–建造者与装饰者

本文探讨了为披萨店构建软件时选择构造器模式和装饰器模式的场景。构造器模式适用于一次性按照规格创建披萨,而装饰器模式则用于动态添加功能。文章通过代码示例展示了两种模式的实现,并在测试用例中验证了它们的效果。总结了两种模式的区别和适用情况,强调了它们在创建和扩展对象时的不同用途。
摘要由CSDN通过智能技术生成
披萨店小程序

披萨店小程序

问题陈述

我们需要为一家披萨公司构建软件,该公司想要准备不同类型的披萨,例如鸡肉披萨,扁平面包,意大利辣香肠披萨和额外的奶酪,并在上面放些配料。

让我们尝试看看哪种设计模式适合该问题说明以及在哪种情况下。 传统上,对于披萨问题,最常用的是构造器模式。 但是,也有一些使用装饰器的示例,两种方法都是正确的,但用例有所不同。 Builder是一种对象创建模式,而装饰器用于在运行时更改已构建的对象。让我们尝试通过示例来理解这一点:

  1. 生成器模式:

    这里的用例是按照既定规格一次性制作披萨。

    让我们来看看披萨课:

    public class Pizza {
    
        private float totalPrice = 0;
    
        private Size size;
        private Topping topping;
        private Crust crust;
        private Cheese cheese;
    
        public Size getSize() {
            return size;
        }
    
        public void setSize(Size size) {
            this.size = size;
        }
    
        public Topping getTopping() {
            return topping;
        }
    
        public void setTopping(Topping topping) {
            this.topping = topping;
        }
    
        public Crust getCrust() {
            return crust;
        }
    
        public void setCrust(Crust crust) {
            this.crust = crust;
        }
    
        public Cheese getCheese() {
            return cheese;
        }
    
        public void setCheese(Cheese cheese) {
            this.cheese = cheese;
        }
    
        public float getTotalPrice() {
            return totalPrice;
        }
    
        public void addToPrice(float price) {
            this.totalPrice = totalPrice + price;
        }
    }

    4个枚举类:

    public enum Cheese {
        AMERICAN {
            public float getCost() {
                return 40;
            }
        }, ITALIAN {
            public float getCost() {
                return 60;
            }
        };
    
        public abstract float getCost();
    
    }
    
    public enum Crust {
    
          THIN  {
            public float getCost(){
                return 70;
            }
        } , STUFFED{
            public float getCost(){
                return 90;
            }
        };
    
        public abstract float getCost();
    }
    
    public enum Size {
        MEDIUM {
            public float getCost() {
                return 100;
            }
        }, LARGE {
            public float getCost() {
                return 160;
            }
        };
    
        public abstract float getCost();
    }
    
    public enum Topping {
    
        PEPPERONI {
            public float getCost(){
                return 30;
            }
        }, CHICKEN{
            public float getCost(){
                return 35;
            }
        }, MUSHROOM{
            public float getCost(){
                return 20;
            }
        };
    
        public abstract float getCost();
    }

    PizzaBuilder类别:

    public class PizzaBuilder {
    
        Pizza pizza = new Pizza();
    
        public PizzaBuilder withTopping(Topping topping) {
            pizza.setTopping(topping);
            pizza.addToPrice(topping.getCost());
            return this;
        }
    
        public PizzaBuilder withSize(Size size) {
            pizza.setSize(size);
            pizza.addToPrice(size.getCost());
            return this;
        }
    
        public PizzaBuilder withCrust(Crust crust) {
            pizza.setCrust(crust);
            pizza.addToPrice(crust.getCost());
            return this;
        }
    
        public Pizza build() {
            return pizza;
        }
    
        public double calculatePrice() {
            return pizza.getTotalPrice();
        }
    
    }

    测试用例:

    public class PizzaBuilderTest {
    
        @Test
        public void shouldBuildThinCrustChickenPizza(){
            Pizza pizza = new PizzaBuilder().withCrust(Crust.THIN).withTopping(Topping.CHICKEN).withSize(Size.LARGE).build();
            assertEquals(Topping.CHICKEN,pizza.getTopping());
            assertEquals(Size.LARGE,pizza.getSize());
            assertEquals(Crust.THIN,pizza.getCrust());
            assertEquals(265.0,pizza.getTotalPrice(),0);
        }
    }
  2. 装饰图案:

    装饰器模式用于动态添加或删除对象的其他功能或职责,而不会影响原始对象。 用例是先准备一些基础比萨,然后再添加不同的规格。

    在这里,我们需要一个要装饰的BasicPizza(混凝土组件)的接口(Pizza)和一个包含Pizza(已装饰)接口的引用字段的PizzaDecorator类。

    披萨界面:

    public interface Pizza {
        public String bakePizza();
        public float getCost();
    }

    基本比萨实施:

    public class BasePizza implements Pizza{
    
        public String bakePizza() {
            return "Basic Pizza";
        }
        public float getCost(){
            return 100;
        }
    }

    PizzaDecorator类:

    public class PizzaDecorator implements Pizza {
        Pizza pizza;
        public PizzaDecorator(Pizza newPizza) {
            this.pizza = newPizza;
        }
    
        public String bakePizza() {
            return pizza.bakePizza();
        }
    
        @Override
        public float getCost() {
            return pizza.getCost();
        }
    }

    2个装饰:蘑菇和意大利辣香肠

    public class Mushroom extends PizzaDecorator {
    
        public Mushroom(Pizza newPizza) {
            super(newPizza);
        }
    
        @Override
        public String bakePizza() {
            return super.bakePizza() + " with Mashroom Topings";
        }
    
        @Override
        public float getCost() {
            return super.getCost()+80;
        }
    }
    public class Pepperoni extends PizzaDecorator {
    
        public Pepperoni(Pizza newPizza) {
            super(newPizza);
        }
    
        @Override
        public String bakePizza() {
            return super.bakePizza() + " with Pepperoni Toppings";
        }
    
        @Override
        public float getCost() {
            return super.getCost()+110;
        }
    }

    测试用例:

    public class PizzaDecoratorTest {
    
        @Test
        public void shouldMakePepperoniPizza(){
            Pizza pizza = new Pepperoni(new BasePizza());
            assertEquals("Basic Pizza with Pepperoni Toppings",pizza.bakePizza());
            assertEquals(210.0,pizza.getCost(),0);
        }
    }

区别

在创建对象时使用了诸如builder和factory(以及abstract factory)之类的模式。 装饰器之类的模式(也称为结构设计模式)用于可扩展性或为已创建的对象提供结构更改。

两种类型的模式在很大程度上都偏重于组合而不是继承,因此将其作为使用builder而不是decorator的区分因素没有任何意义。 两者都在运行时给出行为,而不是继承它。

因此,如果要限制具有某些属性/功能的对象创建,则应使用builder。 例如,在创建对象之前必须设置4-5个属性,否则我们将冻结对象创建直到尚未设置某些属性。 基本上,使用它代替构造函数-正如Joshua Bloch在Effective Java,2nd Edition中指出的那样。 构建器公开了生成的对象应具有的属性,但隐藏了如何设置它们。

装饰器用于添加现有对象的新功能以创建新对象。 在添加对象的所有功能之前,没有冻结对象的限制。 两者都使用合成,因此它们看起来相似,但是在用例和意图上有很大不同。

另一种方法是使用工厂模式。 如果我们不想公开这些属性,而是希望“神奇地”在内部创建某些披萨,则可以基于某些属性。 我们将在后面的文章中使用Factory Pattern探索该实现。

翻译自: https://www.javacodegeeks.com/2014/08/pizza-problem-builder-vs-decorator.html

披萨店小程序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值