La fábrica simple no es un patrón de diseño. Simplemente desacopla la creación de objetos del código del cliente. En otras palabras, Simple Factory encapsula la creación de instancias de objetos moviendo la lógica de creación de instancias a una clase separada.
La fábrica simple a menudo se confunde con el patrón de fábrica. Vamos a estudiar la fábrica simple para aclarar su diferencia. Además, aprender Simple Factory nos ayuda a comprender fácilmente el patrón Factory.
Se debe evitar la programación para una implementación concreta porque hace que una aplicación sea muy difícil de mantener. Siempre es preferible programar a interfaz. Si está creando una instancia de una clase concreta en el código del cliente, entonces Simple factory resulta útil ya que Simple factory puede desacoplar la creación de objetos del cliente. Esto hace que nuestra aplicación sea más extensible y fácil de mantener.
Estamos desarrollando un sistema para hamburguesería. El sistema necesita crear varias hamburguesas, como hamburguesa de ternera, hamburguesa de pollo, etc.
Nuestro primer intento sería así:
// 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; }
El problema es que estamos codificando para la implementación, no para la interfaz. ¿Dónde? Usamos la declaración if y creamos una instancia de una clase concreta basada en un tipo de hamburguesa.
¿Por qué es el problema? ¡Nuestro código de cliente está estrechamente relacionado con la creación de objetos, lo que genera menos flexibilidad! Digamos que ya no vendemos hamburguesas de pescado y empezamos a vender hamburguesas vegetarianas. Necesitamos visitar nuestro código de cliente y modificarlo. Es decir, no está cerrado a modificaciones.
Para resolver el problema, podemos crear una clase separada que será responsable únicamente de la creación de objetos. Entonces nuestro código de cliente no necesita preocuparse por la creación de objetos y poder depender de la abstracción. Esta técnica se conoce como "Encapsular lo que varía". Esperamos que el código sobre la creación de instancias de objetos concretos se cambie con frecuencia, mientras que los procesos prepareBun(), grillPatty(), addToppings(), wrap() probablemente sigan siendo los mismos entre todas las hamburguesas en el futuro.
La ventaja de Simple Factory es que otras clases pueden reutilizarla. Es posible que tengamos otras clases de clientes como BurgerRestaurant, BurgerCateringShop que utilizarán el método SimpleBurgerFactory.createBurger().
Cliente
El cliente crea una instancia de un objeto de hamburguesa específico a través de SimpleBurgerFactory. Observe que desde la perspectiva del cliente, no sabemos qué hamburguesa concreta se creará, es decir, la lógica de creación de objetos ahora está desacoplada del cliente.
SimpleBurgerFactory
¡Esta clase encapsula lo que varía, que es en este caso la lógica de creación de objetos! createBurger() se declara como método estático porque el cliente quiere usar esta clase para crear una instancia del objeto (¡por supuesto que no podemos tener una instancia antes de crear una instancia!). createBurger() acepta la enumeración BurgerType para determinar qué tipo de hamburguesa se debe crear.
Hamburguesa
Esta clase abstracta proporciona una interfaz común entre todas las hamburguesas y define comportamientos predeterminados.
Subclases de hamburguesas
Aquí están nuestros productos de hormigón. Pueden implementar un comportamiento específico anulando métodos siempre que extiendan la clase Burger.
public enum BurgerType { BEEF, CHICKEN, FISH, VEGGIE }
// Abstract Product public abstract class Burger { public BurgerType burgerType; public Listtoppings = 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; Listitems = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce"); toppings.addAll(items); } }
// Concrete product public class VeggieBurger extends Burger { public VeggieBurger() { burgerType = BurgerType.VEGGIE; Listitems = 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"); }; } }
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; } }
Producción:
Preparing a bun Grill a VEGGIE patty Add smoked paprika Add garlic chips Add crushed walnuts Add veggie sauce Wrapping paper shouldn't print any meats but vegetables com.factories.simpleFactory.VeggieBurger@9807454
Puedes consultar todas las implementaciones de patrones de diseño aquí.
Repositorio de GitHub
PD.
Soy nuevo en escribir blogs de tecnología. Si tienes algún consejo para mejorar mi escritura o tienes algún punto confuso, ¡deja un comentario!
Gracias por leer :)
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3