↓Ir al contenido

Patrón de diseño Factory en Java

·3 mins

El patrón de diseño Factory es usado principalmente cuando tenemos una clase o interfaz con muchas subclases o implementaciones y según algún input necesitamos devolver una de estas subclases concretas.

Cuando crear una Factory class #

Pensemos en una interfaz de la cual realizamos luego varias implementaciones. Usemos la típica interfaz de ejemplo Shape de la cual implementamos varias clases Circle, Rectangle, Square.


package patterns.factory;

public interface Shape {
    void draw();
}

package patterns.factory;

public class Circle implements Shape {

    @Override
    public void draw() {
        System.out.println("I am a Circle");
    }

}

package patterns.factory;

public class Rectangle implements Shape {

    @Override
    public void draw() {
        System.out.println("I am a Rectangle");
    }

}

package patterns.factory;

public class Square implements Shape {

    @Override
    public void draw() {
        System.out.println("I am a Square");
    }

}

En este caso tenemos varias implementaciones y según el tipo de Shape que deseamos queremos crear la implementación concreta de la interfaz.

La forma habitual (sin un factory) sería de este modo.


package patterns.factory;

public class FactoryPatternExample {

    public static void main(String[] args) {

        FactoryPatternExample example = new FactoryPatternExample();
        example.printShape("CIRCLE");

    }

    // Whithout factory
    public void printShape(String shapeType) {

        Shape shape;
        switch (shapeType) {
            case "CIRCLE":
                shape = new Circle();
                break;
            case "RECTANGLE":
                shape = new Rectangle();
                break;
            case "SQUARE":
                shape = new Square();
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + shapeType);
        }
        shape.draw();

    }

}

Como crear una Factory class #

Vemos en el ejemplo previo que podríamos simplificar la creación de la clase llevándonos todo lo que esta en el switch a otra clase Factory que se encargue de esto, dejando así nuestro código más simple y claro.

Vamos a crear una clase ShapeFactory para tal fin.


package patterns.factory;

public class ShapeFactory {

    public static Shape getShape(String shapeType) {

        if (shapeType == null) {
            return null;
        }

        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        } else if (shapeType.equalsIgnoreCase("SQUARE")) {
            return new Square();
        } else {
            throw new IllegalStateException("Unexpected value: " + shapeType);
        }

    }

}

Veamos cómo queda ahora nuestro ejemplo previo haciendo uso de nuestra Factory.

Observa que queda mucho más limpio y claro delegando la creación de las instancias a la Factory.

La Factory será ahora la encargada de crear la instancia en particular y nuestra clase main de ejemplo hará uso de esta factory olvidandose de la complejidad para crearla.

Java Factory Pattern

package patterns.factory;

public class FactoryPatternExample {

    public static void main(String[] args) {

        FactoryPatternExample example = new FactoryPatternExample();
        example.printShape("CIRCLE");

    }

    // Using Factory
    public void printShape(String shapeType) {

        Shape shape2 = ShapeFactory.getShape(shapeType);
        shape2.draw();

    }

}

Obviamente este es un ejemplo muy sencillo, en general las Factory class pueden ser más complejas encargándose de crear las instancias bajo condiciones de negocio o diversos inputs que hacen que su uso sea conveniente.

Puedes descargar este código en github