logo

Patrón de diseño del método de fábrica

El patrón de diseño del método de fábrica es un patrón de diseño creacional que proporciona una interfaz para crear objetos en una superclase, permitiendo a las subclases alterar el tipo de objetos que se crearán. Encapsula la lógica de creación de objetos en un método separado, promoviendo un acoplamiento flexible entre el creador y los objetos creados. Este patrón es particularmente útil cuando los tipos exactos de objetos que se crearán pueden variar o deben determinarse en tiempo de ejecución, lo que permite flexibilidad y extensibilidad en la creación de objetos.

Tabla de contenidos



¿Qué es el patrón de diseño del método de fábrica?

El patrón de diseño del método de fábrica es un patrón de diseño creacional utilizado en ingeniería de software para proporcionar una interfaz para crear objetos en una superclase, al tiempo que permite a las subclases alterar el tipo de objetos que se crearán. Encapsula la lógica de creación de objetos en un método separado, abstrayendo el proceso de creación de instancias y promoviendo un acoplamiento flexible entre el creador y los objetos creados. Este patrón permite flexibilidad, extensibilidad y mantenibilidad en el código base al permitir que las subclases definan su propia implementación del método de fábrica para crear tipos específicos de objetos.

c# fecha y hora

¿Cuándo utilizar el patrón de diseño del método de fábrica?

Utilice el patrón de diseño del método de fábrica:

  • Cuando desee encapsular la creación de objetos: Si tiene un proceso de creación de objetos complejo o si el proceso puede variar según las condiciones, encapsular esta lógica en un método de fábrica puede simplificar el código del cliente y promover la reutilización.
  • Cuando desee desacoplar el código del cliente de clases concretas: El uso del patrón de método de fábrica le permite crear objetos a través de una interfaz o clase abstracta, abstrayendo los detalles de implementación específicos de las clases concretas del código del cliente. Esto promueve un acoplamiento flexible y facilita la modificación o ampliación del sistema sin afectar el código del cliente existente.
  • Cuando necesite admitir múltiples variaciones de productos: Si su aplicación necesita crear diferentes variaciones de un producto o si se pueden introducir nuevos tipos de productos en el futuro, el patrón de método de fábrica proporciona una forma flexible de adaptarse a estas variaciones definiendo métodos de fábrica para cada tipo de producto.
  • Cuando desee admitir personalización o configuración: Las fábricas se pueden utilizar para encapsular la lógica de configuración, lo que permite a los clientes personalizar el proceso de creación proporcionando parámetros u opciones de configuración al método de fábrica.

Componentes del patrón de diseño del método de fábrica

1. Creador

Esta es una clase abstracta o una interfaz que declara el método de fábrica. El creador normalmente contiene un método que sirve como fábrica para crear objetos. También puede contener otros métodos que funcionen con los objetos creados.

2. Creador concreto

Las clases de Concrete Creator son subclases de Creator que implementan el método de fábrica para crear tipos específicos de objetos. Cada Concrete Creator es responsable de crear un producto en particular.

3. Producto

Esta es la interfaz o clase abstracta para los objetos que crea el método de fábrica. El Producto define la interfaz común para todos los objetos que el método de fábrica puede crear.

4. Producto de hormigón

Las clases de Productos Concretos son los objetos reales que crea el método de fábrica. Cada clase de Producto concreto implementa la interfaz del Producto o extiende la clase abstracta del Producto.

patrones de software java

Ejemplo de patrón de diseño de método de fábrica

A continuación se muestra el planteamiento del problema para comprender el patrón de diseño del método de fábrica:

Considere una aplicación de software que necesita manejar la creación de varios tipos de vehículos, como vehículos de dos, tres y cuatro ruedas. Cada tipo de vehículo tiene sus propias propiedades y comportamientos específicos.

1. Sin patrón de diseño del método de fábrica

Java
/*package whatever //do not write package name here */ import java.io.*; // Library classes abstract class Vehicle {  public abstract void printVehicle(); } class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } } // Client (or user) class class Client {  private Vehicle pVehicle;  public Client(int type) {  if (type == 1) {  pVehicle = new TwoWheeler();  } else if (type == 2) {  pVehicle = new FourWheeler();  } else {  pVehicle = null;  }  }  public void cleanup() {  if (pVehicle != null) {  pVehicle = null;  }  }  public Vehicle getVehicle() {  return pVehicle;  } } // Driver program public class GFG {  public static void main(String[] args) {  Client pClient = new Client(1);  Vehicle pVehicle = pClient.getVehicle();  if (pVehicle != null) {  pVehicle.printVehicle();  }  pClient.cleanup();  } }>
Producción
I am two wheeler>

¿Cuáles son los problemas con el diseño anterior?

En el diseño de código anterior:

  • Acoplamiento apretado: La clase de clienteClient>instancia directamente las clases concretas (TwoWheeler>yFourWheeler>) según el tipo de entrada proporcionada durante su construcción. Esto conduce a un estrecho acoplamiento entre el cliente y las clases concretas, lo que hace que el código sea difícil de mantener y ampliar.
  • Violación del Principio de Responsabilidad Única (SRP): ElClient>La clase es responsable no solo de determinar qué tipo de vehículo crear una instancia en función del tipo de entrada, sino también de gestionar el ciclo de vida del objeto del vehículo (por ejemplo, limpieza). Esto viola el Principio de Responsabilidad Única, que establece que una clase debe tener sólo una razón para cambiar.
  • Escalabilidad limitada: Agregar un nuevo tipo de vehículo requiere modificar elClient>clase, que viola el principio abierto-cerrado. Este diseño no es escalable porque no puede adaptarse a nuevos tipos de vehículos sin modificar el código existente.

¿Cómo evitamos el problema?

  • Definir interfaz de fábrica: Crear unVehicleFactory>Interfaz o clase abstracta con un método para crear vehículos.
  • Implementar Fábricas de Concreto: Implementar clases de fábrica concretas (TwoWheelerFactory>yFourWheelerFactory>) que implementan elVehicleFactory>interfaz y proporciona métodos para crear instancias de tipos específicos de vehículos.
  • Cliente de refactorización: Modificar elClient>clase para aceptar unVehicleFactory>instancia en lugar de crear instancias directamente de vehículos. El cliente solicitará un vehículo de fábrica, eliminando la necesidad de lógica condicional basada en tipos de vehículos.
  • Flexibilidad mejorada: Con este enfoque, agregar nuevos tipos de vehículos es tan simple como crear una nueva clase de fábrica para el nuevo tipo de vehículo sin modificar el código de cliente existente.

2. Con patrón de diseño del método de fábrica

Dividamos el código en código de componentes:

FábricaMétodoDiseñoPatrón

1. Interfaz del producto

Java
// Product interface representing a vehicle public abstract class Vehicle {  public abstract void printVehicle(); }>

2. Productos de hormigón

Java
// Concrete product classes representing different types of vehicles public class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } public class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } }>

3. Interfaz del creador (interfaz de fábrica)

Java
// Factory interface defining the factory method public interface VehicleFactory {  Vehicle createVehicle(); }>

4. Creadores de hormigón (fábricas de hormigón)

Java
// Concrete factory class for TwoWheeler public class TwoWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new TwoWheeler();  } } // Concrete factory class for FourWheeler public class FourWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new FourWheeler();  } }>

Código completo de este ejemplo:

Java
// Library classes abstract class Vehicle {  public abstract void printVehicle(); } class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } } // Factory Interface interface VehicleFactory {  Vehicle createVehicle(); } // Concrete Factory for TwoWheeler class TwoWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new TwoWheeler();  } } // Concrete Factory for FourWheeler class FourWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new FourWheeler();  } } // Client class class Client {  private Vehicle pVehicle;  public Client(VehicleFactory factory) {  pVehicle = factory.createVehicle();  }  public Vehicle getVehicle() {  return pVehicle;  } } // Driver program public class GFG {  public static void main(String[] args) {  VehicleFactory twoWheelerFactory = new TwoWheelerFactory();  Client twoWheelerClient = new Client(twoWheelerFactory);  Vehicle twoWheeler = twoWheelerClient.getVehicle();  twoWheeler.printVehicle();  VehicleFactory fourWheelerFactory = new FourWheelerFactory();  Client fourWheelerClient = new Client(fourWheelerFactory);  Vehicle fourWheeler = fourWheelerClient.getVehicle();  fourWheeler.printVehicle();  } }>
Producción
I am two wheeler I am four wheeler>

En el código anterior:

convertir una cadena a una fecha
  • Vehicle> sirve como interfaz del Producto, definiendo el método común printVehicle()> que todos los productos concretos deben implementar.
  • TwoWheeler> y FourWheeler> Son clases de productos concretas que representan diferentes tipos de vehículos, implementando el printVehicle()> método.
  • VehicleFactory> actúa como la interfaz del Creador (Interfaz de Fábrica) con un método createVehicle()> representando el método de fábrica.
  • TwoWheelerFactory> y FourWheelerFactory> son clases creadoras concretas (Fábricas de Concreto) que implementan el VehicleFactory> Interfaz para crear instancias de tipos específicos de vehículos.

Casos de uso del patrón de diseño del método de fábrica

A continuación se muestran algunas aplicaciones comunes del patrón Factory Method Design:

  • Marcos creacionales:
    • JDBC (Java Database Connectivity) utiliza ampliamente fábricas para crear conexiones, declaraciones y conjuntos de resultados. Los marcos de inyección de dependencia como Spring y Guice dependen en gran medida de las fábricas para crear y administrar beans.
  • Kits de herramientas GUI:
    • Swing y JavaFX utilizan fábricas para crear componentes de interfaz de usuario como botones, campos de texto y etiquetas, lo que permite la personalización y flexibilidad en el diseño de la interfaz de usuario.
  • Marcos de registro:
    • Los marcos de registro como Log4j y Logback utilizan fábricas para crear registradores con diferentes configuraciones, lo que permite controlar los niveles de registro y los destinos de salida.
  • Serialización y deserialización:
    • Los marcos de serialización de objetos a menudo utilizan fábricas para crear objetos a partir de datos serializados, admitiendo diferentes formatos de serialización y control de versiones.
  • Sistemas de complementos:
    • Los sistemas basados ​​en complementos suelen utilizar fábricas para cargar y crear instancias de complementos de forma dinámica, lo que permite la extensibilidad y personalización.
  • Desarrollo de juegos:
    • Los motores de juegos suelen utilizar fábricas para crear diferentes tipos de objetos, personajes y niveles de juego, promoviendo la organización y la flexibilidad del código.
  • Desarrollo web:
    • Los marcos web a veces utilizan fábricas para crear componentes de vista, controladores y servicios, lo que permite la modularidad y la capacidad de prueba en las aplicaciones web.

Ventajas del patrón de diseño del método de fábrica

Las ventajas del patrón de diseño del método de fábrica son:

1 a 100 número romano
  • Desacoplamiento: Separa la lógica de creación de objetos del código del cliente que utiliza esos objetos. Esto hace que el código sea más flexible y fácil de mantener porque los cambios en el proceso de creación no requieren modificaciones en el código del cliente.
  • Extensibilidad: Es fácil introducir nuevos tipos de productos sin cambiar el código del cliente. Simplemente necesita crear una nueva subclase de Concrete Creator e implementar el método de fábrica para producir el nuevo producto.
  • Comprobabilidad: Simplifica las pruebas unitarias al permitirle simular o eliminar la creación de productos durante las pruebas. Puede probar diferentes implementaciones de productos de forma aislada sin depender de la creación real de objetos.
  • Reutilización del código: El método de fábrica se puede reutilizar en diferentes partes de la aplicación donde se necesita la creación de objetos. Esto promueve la centralización y reutilización de la lógica de creación de objetos.
  • Encapsulación: Oculta las clases de productos concretas del código del cliente, haciendo que el código sea menos dependiente de implementaciones específicas. Esto mejora la mantenibilidad y reduce el acoplamiento.

Desventajas del patrón de diseño del método de fábrica

Las desventajas del patrón de diseño del método de fábrica son:

  • Mayor complejidad: Introduce clases e interfaces adicionales, agregando una capa de abstracción que puede hacer que el código sea más complejo de entender y mantener, especialmente para aquellos que no están familiarizados con el patrón.
  • Gastos generales: El uso de polimorfismo y enlace dinámico puede afectar levemente el rendimiento, aunque esto suele ser insignificante en la mayoría de las aplicaciones.
  • Acoplamiento estrecho dentro de las jerarquías de productos: Los creadores de hormigón todavía están estrechamente vinculados a sus correspondientes productos de hormigón. Los cambios en uno a menudo requieren cambios en el otro.
  • Dependencia de subclases concretas: El código del cliente todavía depende de la clase abstracta Creator, lo que requiere conocimiento de sus subclases concretas para realizar llamadas correctas al método de fábrica.
  • Potencial de uso excesivo: Es importante utilizar el patrón Factory Method con prudencia para evitar realizar demasiada ingeniería en la aplicación. La creación de objetos simples a menudo se puede realizar directamente sin necesidad de una fábrica.
  • Desafíos de prueba: Probar la lógica de la fábrica en sí puede ser más complejo.