JavaRush /Blog Java /Random-FR /Problèmes de pizzéria. Constructeur vs Décorateur.
CynepHy6
Niveau 34
Великий Новгород

Problèmes de pizzéria. Constructeur vs Décorateur.

Publié dans le groupe Random-FR

Description du problème.

Nous devons écrire un programme. Pour une pizzeria qui souhaite préparer différents types de pizza : Poulet, Américaine, Viande, Hawaïenne, Pepperoni, etc. Voyons quel modèle et sous quel scénario convient pour résoudre ce problème. Traditionnellement, le modèle Builder est utilisé pour résoudre les « problèmes de pizza ». Il existe également des exemples d'utilisation du motif Décorateur, les deux motifs sont corrects, mais il existe des différences d'utilisation. Le Builder est un modèle pour créer des objets, tandis que le Decorator est utilisé pour modifier l'objet fini à la volée. Essayons de comprendre cela avec des exemples :

1. Générateur de modèles :

Dans ce cas, la pizza est préparée avec tous les ingrédients d’un coup.
Cours de pizza :
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 classes d'énumération :
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(); }
Classe 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(); } }
Examen de classe :
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. Modèle de décorateur :

Le modèle Décorateur est utilisé pour ajouter ou supprimer dynamiquement des fonctionnalités supplémentaires à un objet sans affecter l’objet d’origine. Utilisé lorsqu'une base de pizza est d'abord préparée, puis divers ingrédients sont ajoutés. Ici, nous avons besoin d'une interface (Pizza) pour BasePizza (le composant fondamental) que nous voulons décorer et d'une classe PizzaDecorator qui implémente réellement l'interface.
Interface pizzas :
public interface Pizza { public String bakePizza(); public float getCost(); }
Implémentation dans BasePizza :
public class BasePizza implements Pizza{ public String bakePizza() { return "Basic Pizza"; } public float getCost(){ return 100; } }
Classe 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 décorateurs : Champignon et Pepperoni
public class Mushroom extends PizzaDecorator { public Mushroom(Pizza newPizza) { super(newPizza); } @Override public String bakePizza() { return super.bakePizza() + " with Mushroom 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; } }
Examen de classe :
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); } }

Différences

Des modèles tels que Builder et Factory (et Abstract Factory) sont utilisés dans la création de nouveaux objets. Et des modèles tels que Decorator (également appelés modèles de conception structurelle) sont utilisés à des fins d'extensibilité ou pour apporter des modifications structurelles à des objets déjà créés. Les deux types de modèles favorisent principalement la composition par héritage, et les différences ne sont pas suffisamment significatives pour justifier l'utilisation d'un constructeur au lieu d'un décorateur. Les deux donnent leur propre comportement lorsqu'ils sont exécutés, plutôt que d'en hériter. Dans un cas, il est préférable d'utiliser le Builder - si nous voulons limiter la création d'objets avec certaines propriétés/fonctions. Par exemple, 4 à 5 attributs doivent être définis avant de créer un objet, ou nous souhaitons geler la création d'un objet jusqu'à ce que certains attributs soient déjà définis. En termes simples, utilisez-le à la place d'un constructeur - comme l'écrit Joshua Bloch dans Java : Effective Programming, 2e éd. Le constructeur fournit les attributs que l'objet généré doit avoir mais cache comment les définir. Un décorateur est utilisé pour ajouter de nouvelles propriétés à un objet existant lors de la création d'un nouvel objet basé sur celui-ci. Il n'y a aucune restriction sur le gel d'un objet pendant que toutes ses fonctionnalités sont ajoutées. Les deux modèles utilisent la composition et peuvent se ressembler. La principale différence réside dans leur utilisation.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION