Desarrollo

El patrón Factory Method

Publicado el
Etiquetas: golang python patterns design patterns c# java
El patrón Factory Method
Comparte

El patrón de diseño Factory Method es un patrón creacional que se utiliza para crear objetos sin especificar la clase exacta de objeto que se creará. Este patrón es muy útil cuando se necesita crear objetos que pertenecen a una familia de objetos relacionados, pero se desconoce de antemano la clase exacta del objeto a crear.

En lugar de llamar directamente al constructor del objeto, el código llama a un método de fábrica que se encarga de crear y devolver la instancia del objeto. Esto permite la flexibilidad de cambiar las clases concretas de los objetos que se crean sin cambiar el código que utiliza los objetos.

Para implementar el patrón Factory Method, se requiere la creación de una interfaz o clase abstracta que declara el método de fábrica. Luego se crean las clases concretas que implementan esta interfaz o clase abstracta y proporcionan su propia implementación del método de fábrica para crear objetos. Finalmente, se utiliza el método de fábrica para crear los objetos.

Ejemplos

Un ejemplo concreto de este patrón en Java sería el uso de la interfaz AnimalFactory y sus implementaciones concretas CatFactory y DogFactory. La interfaz AnimalFactory declara el método de fábrica createAnimal(), que es implementado por las clases CatFactory y DogFactory. Estas clases concretas se encargan de crear y devolver instancias de Cat y Dog, respectivamente.

public interface AnimalFactory {
    Animal createAnimal();
}

public class CatFactory implements AnimalFactory {
    public Animal createAnimal() {
        return new Cat();
    }
}

public class DogFactory implements AnimalFactory {
    public Animal createAnimal() {
        return new Dog();
    }
}

En Python, se puede implementar el patrón Factory Method utilizando una clase abstracta y sus subclases concretas. Por ejemplo, se puede tener la clase abstracta Pizza y sus subclases concretas CheesePizza y PepperoniPizza. La clase abstracta Pizza declara el método de fábrica create_pizza(), que es implementado por las subclases concretas.

from abc import ABC, abstractmethod

class Pizza(ABC):
    @abstractmethod
    def create_pizza(self):
        pass

class CheesePizza(Pizza):
    def create_pizza(self):
        return "Cheese Pizza"

class PepperoniPizza(Pizza):
    def create_pizza(self):
        return "Pepperoni Pizza"

En Go, se puede implementar este patrón utilizando una interfaz y sus implementaciones concretas. Por ejemplo, se puede tener la interfaz ShapeFactory y sus implementaciones concretas RectangleFactory y CircleFactory. La interfaz ShapeFactory declara el método de fábrica CreateShape(), que es implementado por las clases RectangleFactory y CircleFactory. Estas clases concretas se encargan de crear y devolver instancias de Rectangle y Circle, respectivamente.

type ShapeFactory interface {
    CreateShape() Shape
}

type RectangleFactory struct {}

func (rf RectangleFactory) CreateShape() Shape {
    return Rectangle{}
}

type CircleFactory struct {}

func (cf CircleFactory) CreateShape() Shape {
    return Circle{}
}

En C#, se puede implementar el patrón Factory Method utilizando una interfaz y sus implementaciones, por ejemplo:

// Interfaz del producto
public interface IProduct
{
    void DoSomething();
}

// Clase concreta del producto
public class ConcreteProductA : IProduct
{
    public void DoSomething()
    {
        Console.WriteLine("Do something from ConcreteProductA");
    }
}

// Otra clase concreta del producto
public class ConcreteProductB : IProduct
{
    public void DoSomething()
    {
        Console.WriteLine("Do something from ConcreteProductB");
    }
}

// Interfaz de la fábrica
public interface IFactory
{
    IProduct CreateProduct();
}

// Implementación concreta de la fábrica que crea objetos de tipo ConcreteProductA
public class ConcreteFactoryA : IFactory
{
    public IProduct CreateProduct()
    {
        return new ConcreteProductA();
    }
}

// Implementación concreta de la fábrica que crea objetos de tipo ConcreteProductB
public class ConcreteFactoryB : IFactory
{
    public IProduct CreateProduct()
    {
        return new ConcreteProductB();
    }
}

// Uso de la fábrica
public class Client
{
    private IFactory factory;

    public Client(IFactory factory)
    {
        this.factory = factory;
    }

    public void DoSomethingWithProduct()
    {
        IProduct product = factory.CreateProduct();
        product.DoSomething();
    }
}

// Ejemplo de uso
public static void Main()
{
    IFactory factoryA = new ConcreteFactoryA();
    Client clientA = new Client(factoryA);
    clientA.DoSomethingWithProduct(); // Salida: "Do something from ConcreteProductA"

    IFactory factoryB = new ConcreteFactoryB();
    Client clientB = new Client(factoryB);
    clientB.DoSomethingWithProduct(); // Salida: "Do something from ConcreteProductB"
}

En este ejemplo, la interfaz IProduct define el comportamiento de los productos que se pueden crear. Luego se definen dos clases concretas ConcreteProductA y ConcreteProductB que implementan esta interfaz y proporcionan su propia implementación del método DoSomething().

La interfaz IFactory define el método CreateProduct() que las fábricas deben implementar para crear instancias de IProduct. Luego se definen dos implementaciones concretas de la fábrica ConcreteFactoryA y ConcreteFactoryB que crean objetos de tipo ConcreteProductA y ConcreteProductB, respectivamente.

Finalmente, la clase Client utiliza una instancia de IFactory para crear instancias de IProduct y llamar al método DoSomething(). En el ejemplo, se crean dos instancias de Client, cada una con una fábrica diferente, lo que les permite crear diferentes tipos de productos.

Conclusiones

El patrón de diseño Factory Method proporciona una forma flexible de crear objetos sin especificar la clase exacta de objeto que se creará. Esto permite que el código se adapte a diferentes tipos de objetos sin tener que modificar el código que utiliza los objetos.

Las ventajas de utilizar este patrón incluyen:

  • Flexibilidad
    El patrón Factory Method permite que el código sea flexible y adaptable a diferentes tipos de objetos. Si se necesita cambiar la clase concreta de un objeto, simplemente se debe crear una nueva clase que implemente la interfaz o clase abstracta del producto y se modifica la fábrica para crear instancias de esta nueva clase.
  • Mantenibilidad
    Al utilizar este patrón, el código es más mantenible y fácil de modificar. Si se necesita agregar un nuevo tipo de producto, solo se debe crear una nueva clase concreta y una nueva fábrica que pueda crear instancias de esta nueva clase.
  • Separación de responsabilidades
    El patrón Factory Method separa la responsabilidad de crear objetos de la lógica del negocio. Esto permite que el código sea más modular y que cada clase se centre en su propia tarea específica.
  • Reutilización de código
    Al utilizar este patrón, se puede reutilizar código existente para crear nuevas implementaciones de productos. Esto permite que el código sea más eficiente y que se evite la duplicación de código.

En resumen, el patrón de diseño Factory Method proporciona una forma flexible y mantenible de crear objetos en el código. Al utilizar este patrón, se puede separar la responsabilidad de crear objetos de la lógica del negocio, lo que permite que el código sea más modular y reutilizable.

Javier Sanchez Toledano
Escrito por Javier Sanchez Toledano Sígueme

Soy Licenciado en Informática e Ingeniero en Sistemas Computacionales.
Soy auditor líder certificado por ICA en la Norma ISO 9000, desarrollo sistemas de gestión de la calidad con un enfoque de mejora continua, creo tableros de control con indicadores clave para mejorar la toma de decisiones basadas en datos.

Comentarios