分披萨问题_比萨问题–建造者与装饰者
分披薩問題
問題陳述
我們需要為一家披薩公司構建軟件,該公司想要準備不同類型的披薩,例如雞肉披薩,扁平面包,意大利辣香腸披薩和特制奶酪,并在上面放些配料。
讓我們嘗試看看哪種設計模式適合該問題說明以及在哪種情況下。 傳統上,對于披薩問題,最常用的是構造器模式。 但是,也有一些使用裝飾器的示例,兩種方法都是正確的,但用例有所不同。 Builder是一種對象創建模式,而裝飾器用于在運行時更改已構建的對象。
讓我們嘗試通過示例來理解這一點:
生成器模式:
這里的用例是按照既定規格一次性制作披薩。
讓我們來看看披薩課:
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);} }裝飾圖案:
裝飾器模式用于動態添加或刪除對象的其他功能或職責,而不會影響原始對象。 用例是先準備一些基礎比薩,然后再添加不同的規格。
在這里,我們需要一個要裝飾的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。 例如,在創建對象之前必須設置4-5個屬性,否則我們將凍結對象創建直到尚未設置某些屬性。 基本上,使用它代替構造函數-正如Joshua Bloch在Effective Java,2nd Edition中指出的那樣。 構建器公開了生成的對象應具有的屬性,但隱藏了如何設置它們。
裝飾器用于添加現有對象的新功能以創建新對象。 在添加對象的所有功能之前,沒有凍結對象的限制。 兩者都使用合成,因此它們看起來可能相似,但是在用例和意圖上有很大不同。
另一種方法是使用工廠模式。 如果我們不想公開這些屬性,而是希望“神奇地”在內部創建某些披薩,則可以基于某些屬性。 我們將在以后的文章中使用Factory Pattern探索該實現。
翻譯自: https://www.javacodegeeks.com/2014/08/pizza-problem-builder-vs-decorator.html
分披薩問題
總結
以上是生活随笔為你收集整理的分披萨问题_比萨问题–建造者与装饰者的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZeptoN正在将程序放入Java
- 下一篇: 绿色的衣服配什么颜色的裤子好看 绿色的衣