问题陈述

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

让我们尝试看看哪种设计模式适合该问题说明以及在哪种情况下。 传统上,对于披萨问题,最常用的是构造器模式。 但是,也有一些使用装饰器的示例,两种方法都是正确的,但用例有所不同。 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 {@Testpublic 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();}@Overridepublic float getCost() {return pizza.getCost();}
    }

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

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

    测试用例:

    public class PizzaDecoratorTest {@Testpublic 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

比萨问题–建造者与装饰者相关推荐

  1. 分披萨问题_比萨问题–建造者与装饰者

    分披萨问题 问题陈述 我们需要为一家披萨公司构建软件,该公司想要准备不同类型的披萨,例如鸡肉披萨,扁平面包,意大利辣香肠披萨和特制奶酪,并在上面放些配料. 让我们尝试看看哪种设计模式适合该问题说明以及 ...

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

    披萨店小程序 问题陈述 我们需要为一家披萨公司构建软件,该公司想要准备不同类型的披萨,例如鸡肉披萨,扁平面包,意大利辣香肠披萨和额外的奶酪,并在上面放些配料. 让我们尝试看看哪种设计模式适合该问题说明 ...

  3. 2019 Android 高级面试题总结 从java语言到AIDL使用与原理

    说下你所知道的设计模式与使用场景 a.建造者模式: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 使用场景比如最常见的AlertDialog,拿我们开发过程中举例,比如C ...

  4. 分享Android资深架构师的成长之路,建议收藏

    背景 经常有网友在知乎问答提两个问题:"现在学习移动开发还有前景吗?""开发还有什么可以研究的?".网友回复:"现在还学移动开发?如同49年加入国军! ...

  5. 2021华为Android面试真题解析Android面试题集锦,一文轻松搞定

    前言 19年6月份从网易云音乐离开,放弃了留学机会,开始了人生的第一次创业,前后尝试了两个项目,因为个人能力与时机因素都失败了,虽然没能享受到创业所能够带来高杠杆物质上的回报,但是对个人软技能和自我边 ...

  6. 2019 Android 高级面试题总结

    作者:雨林沐风rzm 链接:https://www.jianshu.com/p/461bf99964ec 声明:本文已获雨林沐风rzm授权发表,转发等请联系原作者授权 说下你所知道的设计模式与使用场景 ...

  7. 2019Android高级面试题总结

    Linux编程点击右侧关注,免费入门到精通! 作者丨雨林沐风rzm https://www.jianshu.com/p/461bf99964ec 说下你所知道的设计模式与使用场景 a.建造者模式: 将 ...

  8. python技术分享

    文章目录 python介绍 应用领域 环境搭建 基础知识 编程工具 变量 基本数据类型 容器数据类型 程序结构 运算符 函数 类 技巧总结 python内存管理 python常用技术 python的缺 ...

  9. 7年老Android一次操蛋的面试经历,附小技巧

    前言 作为一个程序员,如果你在新知识.新技术面前仍一无所知,依然吃着十多年前的老本,那你在知识技术上肯定落伍,如果又未能进入管理层面,那你肯定就会被长江的后浪拍在沙滩上了. 而不少与时俱进.善于学习的 ...

最新文章

  1. python代码计算图像的分辨率
  2. React Native StyleSheet 样式属性
  3. 工程师文化播客: 从工程转向管理,访谈Github公司的Phil Haack
  4. linux ora 00119,ORA-00119和ORA-00132的解决方案
  5. 【数据结构与算法】之“寻找两个正序数组的中位数”的求解思路和算法示例
  6. The authenticity of host 'github.com (52.74.223.119)' can't be established.
  7. 原生mysql启动_单实例MySQL的启动和关闭的方法
  8. 并发机制:CSP vs Actor模型以及Golang实现
  9. 苹果沦为语音识别领域失败者?
  10. XcodeGhost事件或成年内最严重信息安全事件
  11. 如何将wav文件切成多个子文件
  12. pm2 for linux
  13. 如何做好PPT——画图篇
  14. 报考华为认证考试流程
  15. wireshark IP地址域名解析
  16. 特大通知!!!CSDN和简书博客以后同步更新
  17. img加载中显示loading,加载失败显示默认图片(React)
  18. 模式识别与人工智能官网,人工智能模式识别技术
  19. 超级计算机 在线 算命,IBM机器人会算命:100个字看穿你灵魂
  20. POJ 1419 【最大团模板解析】

热门文章

  1. 3-1 Apache Shiro权限管理框架介绍
  2. Android Bitmap OutOfMemory 解决办法
  3. python开发stm32软件_ADB+Python+STM32 实现 微信跳一跳辅助
  4. vue框架项目部署到服务器_在浏览器中在线尝试无服务器框架项目!
  5. latex如何使节标题居左_为使节构建控制平面的指南第3部分-特定于域的配置API...
  6. java 验证码透明背景_Java中的证书透明度验证
  7. 震惊kafka_5个令人震惊的统计数据证明日志不足
  8. java 精选选择题_Java生产率提示:社区精选
  9. 杜克大学_记录链接:与杜克一起玩
  10. lua中keyvalue_40行中的持久性KeyValue Server和一个可悲的事实