C'est le début d'une série de blogs sur les Design Patterns. Dans ce blog, nous aborderons le premier type de modèle de conception, les modèles de création. Ici, les types qui relèvent des modèles créationnels seront discutés avec quelques exemples concrets. J'utiliserai Java comme langage de sélection.
Les modèles de conception jouent un rôle crucial dans le développement de logiciels, en fournissant des solutions éprouvées aux problèmes courants et en promouvant les meilleures pratiques. Ils sont comme des plans prédéfinis que vous pouvez personnaliser pour résoudre un problème de conception récurrent dans votre code.
Dans la programmation orientée objet, les modèles de conception créationnelle jouent un rôle important car ils permettent de séparer l'instanciation des objets de leur utilisation, augmentant ainsi la flexibilité et l'évolutivité de la création d'objets. Cet article de blog se concentrera sur cinq principaux types de modèles de conception créationnelle : Factory Method, Abstract Factory, Builder, Prototype et Singleton. Pour montrer comment chacun fonctionne, nous utiliserons des exemples concrets en Java.
1. Méthode d'usine
Le modèle Factory Method définit une interface pour créer un objet mais permet aux sous-classes de modifier le type d'objets qui seront créés. Ce modèle prend en charge le couplage lâche en Java pour éviter d'avoir à lier des classes spécifiques à l'application dans le code.
Scénario réel : imaginez une entreprise de logistique qui transporte des marchandises à l'aide de divers véhicules tels que des camions et des navires. Le type de véhicule dépend du mode de transport souhaité.
// Product Interface interface Transport { void deliver(); } // Concrete Products class Truck implements Transport { @Override public void deliver() { System.out.println("Deliver by land in a truck."); } } class Ship implements Transport { @Override public void deliver() { System.out.println("Deliver by sea in a ship."); } } // Creator abstract class Logistics { public abstract Transport createTransport(); public void planDelivery() { Transport transport = createTransport(); transport.deliver(); } } // Concrete Creators class RoadLogistics extends Logistics { @Override public Transport createTransport() { return new Truck(); } } class SeaLogistics extends Logistics { @Override public Transport createTransport() { return new Ship(); } } // let's call the main class public class Main { public static void main(String[] args) { Logistics logistics = new RoadLogistics(); logistics.planDelivery(); logistics = new SeaLogistics(); logistics.planDelivery(); } }
2. Usine abstraite
Le modèle Abstract Factory fournit une interface permettant de créer des familles d'objets liés ou dépendants sans spécifier leurs classes concrètes. C'est utile lorsque le système doit être indépendant de la façon dont ses objets sont créés.
Scénario réel : Imaginez un magasin de meubles qui vend différents types d'ensembles de meubles, tels que des meubles victoriens et modernes. Chaque ensemble comprend des produits comme des chaises et des canapés.
// Abstract Products interface Chair { void sitOn(); } interface Sofa { void lieOn(); } // Concrete Products class VictorianChair implements Chair { @Override public void sitOn() { System.out.println("Sitting on a Victorian chair."); } } class ModernChair implements Chair { @Override public void sitOn() { System.out.println("Sitting on a Modern chair."); } } class VictorianSofa implements Sofa { @Override public void lieOn() { System.out.println("Lying on a Victorian sofa."); } } class ModernSofa implements Sofa { @Override public void lieOn() { System.out.println("Lying on a Modern sofa."); } } // Abstract Factory interface FurnitureFactory { Chair createChair(); Sofa createSofa(); } // Concrete Factories class VictorianFurnitureFactory implements FurnitureFactory { @Override public Chair createChair() { return new VictorianChair(); } @Override public Sofa createSofa() { return new VictorianSofa(); } } class ModernFurnitureFactory implements FurnitureFactory { @Override public Chair createChair() { return new ModernChair(); } @Override public Sofa createSofa() { return new ModernSofa(); } } // Client code public class Main { private static void createFurniture(FurnitureFactory factory) { Chair chair = factory.createChair(); Sofa sofa = factory.createSofa(); chair.sitOn(); sofa.lieOn(); } public static void main(String[] args) { FurnitureFactory victorianFactory = new VictorianFurnitureFactory(); createFurniture(victorianFactory); FurnitureFactory modernFactory = new ModernFurnitureFactory(); createFurniture(modernFactory); } }
3. Constructeur
Le modèle Builder sépare la construction d'un objet complexe de sa représentation, permettant au même processus de construction de créer différentes représentations. Il est particulièrement utile pour créer des objets avec de nombreux attributs facultatifs.
Scénario réel : envisagez un système de commande de pizzas en ligne dans lequel les clients peuvent personnaliser leurs pizzas avec différentes garnitures, tailles et types de croûte.
// Product class Pizza { private String dough = ""; private String sauce = ""; private String topping = ""; public void setDough(String dough) { this.dough = dough; } public void setSauce(String sauce) { this.sauce = sauce; } public void setTopping(String topping) { this.topping = topping; } @Override public String toString() { return "Pizza [dough=" + dough + ", sauce=" + sauce + ", topping=" + topping + "]"; } } // Builder Interface interface PizzaBuilder { void buildDough(); void buildSauce(); void buildTopping(); Pizza getPizza(); } // Concrete Builders class HawaiianPizzaBuilder implements PizzaBuilder { private Pizza pizza; public HawaiianPizzaBuilder() { this.pizza = new Pizza(); } @Override public void buildDough() { pizza.setDough("cross"); } @Override public void buildSauce() { pizza.setSauce("mild"); } @Override public void buildTopping() { pizza.setTopping("ham+pineapple"); } @Override public Pizza getPizza() { return this.pizza; } } class SpicyPizzaBuilder implements PizzaBuilder { private Pizza pizza; public SpicyPizzaBuilder() { this.pizza = new Pizza(); } @Override public void buildDough() { pizza.setDough("pan baked"); } @Override public void buildSauce() { pizza.setSauce("hot"); } @Override public void buildTopping() { pizza.setTopping("pepperoni+salami"); } @Override public Pizza getPizza() { return this.pizza; } } // Director class Waiter { private PizzaBuilder pizzaBuilder; public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; } public Pizza getPizza() { return pizzaBuilder.getPizza(); } public void constructPizza() { pizzaBuilder.buildDough(); pizzaBuilder.buildSauce(); pizzaBuilder.buildTopping(); } } // Client code public class Main { public static void main(String[] args) { Waiter waiter = new Waiter(); PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder(); PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder(); waiter.setPizzaBuilder(hawaiianPizzaBuilder); waiter.constructPizza(); Pizza pizza1 = waiter.getPizza(); System.out.println("Pizza built: " + pizza1); waiter.setPizzaBuilder(spicyPizzaBuilder); waiter.constructPizza(); Pizza pizza2 = waiter.getPizza(); System.out.println("Pizza built: " + pizza2); } }
4. Prototype
Le modèle Prototype est utilisé pour créer un nouvel objet en copiant un objet existant, appelé prototype. Ce modèle est utile lorsque le coût de création d'un nouvel objet est élevé.
Scénario réel : pensez à un éditeur graphique dans lequel vous pouvez créer, dupliquer et modifier des formes.
import java.util.HashMap; import java.util.Map; // Prototype abstract class Shape implements Cloneable { private String id; protected String type; abstract void draw(); public String getType() { return type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } } // Concrete Prototypes class Rectangle extends Shape { public Rectangle() { type = "Rectangle"; } @Override public void draw() { System.out.println("Drawing a Rectangle."); } } class Circle extends Shape { public Circle() { type = "Circle"; } @Override public void draw() { System.out.println("Drawing a Circle."); } } // Prototype Registry class ShapeCache { private static Map<String, Shape> shapeMap = new HashMap<>(); public static Shape getShape(String shapeId) { Shape cachedShape = shapeMap.get(shapeId); return (Shape) cachedShape.clone(); } public static void loadCache() { Rectangle rectangle = new Rectangle(); rectangle.setId("1"); shapeMap.put(rectangle.getId(), rectangle); Circle circle = new Circle(); circle.setId("2"); shapeMap.put(circle.getId(), circle); } } // Client code public class Main { public static void main(String[] args) { ShapeCache.loadCache(); Shape clonedShape1 = ShapeCache.getShape("1"); System.out.println("Shape: " + clonedShape1.getType()); Shape clonedShape2 = ShapeCache.getShape("2"); System.out.println("Shape: " + clonedShape2.getType()); } }
5. Singleton
Le modèle Singleton garantit qu'une classe n'a qu'une seule instance et fournit un point d'accès global à celle-ci. Ce modèle est couramment utilisé pour la journalisation, la mise en cache et les pools de threads.
Scénario réel : imaginez un spouleur d'imprimante où une seule instance devrait gérer toutes les tâches d'impression.
class PrinterSpooler { private static PrinterSpooler instance; private PrinterSpooler() { // private constructor to prevent instantiation } public static PrinterSpooler getInstance() { if (instance == null) { instance = new PrinterSpooler(); } return instance; } public void print(String document) { System.out.println("Printing document: " + document); } } // Client code public class Main { public static void main(String[] args) { PrinterSpooler spooler1 = PrinterSpooler.getInstance(); PrinterSpooler spooler2 = PrinterSpooler.getInstance(); spooler1.print("Document 1"); spooler2.print("Document 2"); System.out.println("Are both spoolers the same instance? " + (spooler1 == spooler2)); } }
https://refactoring.guru/
https://www.javatpoint.com/design-patterns-in-java
https://www.digitalocean.com/community/tutorials/java-design-patterns-example-tutorial
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!