Une usine simple n’est pas un modèle de conception. Il dissocie simplement la création d'objets du code client. En d'autres termes, Simple Factory encapsule l'instanciation d'objet en déplaçant la logique d'instanciation vers une classe distincte.
L'usine simple est souvent confondue avec le modèle d'usine. Nous allons étudier Simple Factory pour clarifier leur différence. De plus, l'apprentissage de Simple Factory nous aide à comprendre facilement le modèle Factory.
La programmation pour une mise en œuvre concrète doit être évitée car elle rend une application très difficile à maintenir. Il est toujours préférable de programmer pour interfacer. Si vous instanciez une classe concrète dans le code client, alors Simple Factory s'avère pratique car Simple Factory peut dissocier la création d'objets du client. Cela rend notre application plus extensible et maintenable.
Nous développons un système pour Burger Shop. Le système doit créer divers hamburgers tels qu'un hamburger au bœuf, un hamburger au poulet, etc.
Notre première tentative ressemblerait à ceci :
// Client orders a burger Burger orderBurger(String type) { Burger burger; if (type.equals("beef")) { burger = new BeefBurger(); } else if (type.equals("chicken")) { burger = new ChickenBurger(); } else if (type.equals("fish")) { burger = new FishBurger(); } burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; }
Le problème est que nous codons pour l'implémentation et non pour l'interface. Où? Nous utilisons l'instruction if et instancions une classe concrète basée sur un type de burger.
Pourquoi est-ce le problème ? Notre code client est étroitement couplé à la création d'objets, ce qui entraîne moins de flexibilité !! Disons que si nous ne vendons plus de burgers au poisson, et commençons à vendre des burgers végétariens. Nous devons visiter notre code client et le modifier. C'est-à-dire qu'il n'est pas fermé à modification.
Pour résoudre le problème, nous pouvons créer une classe distincte qui sera responsable uniquement de la création d'objets. Notre code client n'a alors pas besoin de se soucier de la création d'objets et peut dépendre de l'abstraction. Cette technique est connue sous le nom de "Encapsuler ce qui varie". Nous nous attendons à ce que le code d'instanciation des objets concrets soit modifié fréquemment, tandis que les processus prepareBun(), grillPatty(), addToppings(), wrap() resteront probablement les mêmes parmi tous les hamburgers à l'avenir.
L’avantage de Simple factory est qu’elle est réutilisable par d’autres classes. Nous pourrions avoir d'autres classes client telles que BurgerRestaurant, BurgerCateringShop qui utiliseront la méthode SimpleBurgerFactory.createBurger().
Client
Le client instancie un objet burger spécifique via SimpleBurgerFactory. Remarquez du point de vue du client, nous ne savons pas quel hamburger concret sera créé, c'est-à-dire que la logique de création d'objet est désormais découplée du client.
SimpleBurgerFactory
Cette classe encapsule ce qui varie, qui est dans ce cas la logique de création d'objet ! createBurger() est déclarée comme méthode statique car le client souhaite utiliser cette classe pour instancier un objet (bien sûr, nous ne pouvons pas avoir d'instance avant de l'instancier !). createBurger() accepte l'énumération BurgerType pour déterminer quel type de hamburger doit être créé.
Hamburger
Cette classe abstraite fournit une interface commune à tous les hamburgers et définit les comportements par défaut.
Sous-classes de hamburgers
Voici nos produits en béton. Ils peuvent implémenter un comportement spécifique en remplaçant les méthodes tant qu'ils étendent la classe Burger.
// Client orders a burger Burger orderBurger(String type) { Burger burger; if (type.equals("beef")) { burger = new BeefBurger(); } else if (type.equals("chicken")) { burger = new ChickenBurger(); } else if (type.equals("fish")) { burger = new FishBurger(); } burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; }
public enum BurgerType { BEEF, CHICKEN, FISH, VEGGIE }
// Abstract Product public abstract class Burger { public BurgerType burgerType; public List<String> toppings = new ArrayList<>(); public void prepareBun() { System.out.println("Preparing a bun"); } public void grillPatty() { if (burgerType == null) { throw new IllegalStateException("pattyType is undefined"); } System.out.println("Grill a " + burgerType + " patty"); } public void addToppings() { for (String item : toppings) { System.out.println("Add " + item); } } public void wrap() { System.out.println("Wrap a burger up"); } }
// Concrete product public class BeefBurger extends Burger { public BeefBurger() { burgerType = BurgerType.BEEF; List<String> items = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce"); toppings.addAll(items); } }
// Concrete product public class VeggieBurger extends Burger { public VeggieBurger() { burgerType = BurgerType.VEGGIE; List<String> items = List.of("smoked paprika", "garlic chips", "crushed walnuts", "veggie sauce"); toppings.addAll(items); } // Concrete product can implement specific behavior that differs from other products @Override public void wrap() { System.out.println("Wrapping paper shouldn't print any meats but vegetables"); } }
// Simple factory, responsible for instantiating an object public class SimpleBurgerFactory { public static Burger createBurger(BurgerType type) { return switch (type) { case BEEF -> new BeefBurger(); case CHICKEN -> new ChickenBurger(); case FISH -> new FishBurger(); case VEGGIE -> new VeggieBurger(); default -> throw new IllegalArgumentException("unknown burger type"); }; } }
Sortie :
public class Client { public static void main(String[] args) { Burger burger = orderBurger(BurgerType.VEGGIE); System.out.println(burger); // Check if the object is actually veggie burger } public static Burger orderBurger(BurgerType type) { // Factory is responsible for object creation Burger burger = SimpleBurgerFactory.createBurger(type); burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; } }
Vous pouvez consulter toutes les implémentations de modèles de conception ici.
Dépôt GitHub
P.S.
Je suis nouveau dans l'écriture d'un blog technique, si vous avez des conseils pour améliorer mon écriture ou si vous avez un point déroutant, veuillez laisser un commentaire !
Merci d'avoir lu :)
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!