DEV Community

Cover image for Static factory method
Elías Canales
Elías Canales

Posted on

Static factory method

El static factory method es un patrón creacional que permite crear objetos usando un método en vez de un constructor.

//Constructor
final A a = new A();

//Static factory method
final A a = A.instance();
Enter fullscreen mode Exit fullscreen mode

En un primer momento puede parecer que hacer eso no tiene ninguna utilidad, pero si lo vemos en más profundidad podemos empezar a ver las ventajas.

//Constructor
final A a = new A(1, 2);

//Static factory method
final A a = A.fromWidthAndHeight(1, 2);
Enter fullscreen mode Exit fullscreen mode

Ahora claramente se ve una diferencia, y es que es mucho más fácil saber que es cada parámetro. Al usar métodos estáticos podemos aprovechar el nombre del método para dar contexto de lo que vamos a usar.

Al no usar constructores, no es necesario devolver siempre una nueva instancia, podemos reutilizar una existente. Esto hace que si tenemos un número reducido de opciones (como un Enum), podríamos tener preparadas las instancias y devolverlas.

private static final A DEFAULT_RECTANGLE = new Rectangle(100, 100);    

public static A fromWidthAndHeight(final int width, final int height) {
    if (width == 100 && height == 100) {
        return DEFAULT_RECTANGLE;
    }

    return new A(width, height);
}
Enter fullscreen mode Exit fullscreen mode

Otra ventaja es que podemos devolver subclases, al estar usando un método estático, no tenemos por qué devolver la misma clase. Y eso a su vez permite ocultar clases.

public interface Animal {
    void makeSound();

    static Animal createDog() {
        return new Dog();
    }
}

// Dog puede ser privado o package-private
class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}
Enter fullscreen mode Exit fullscreen mode

Similar a lo anterior, dependiendo de los parámetros podemos devolver clases distintas llamando al mismo método.

public interface Animal {
    void makeSound();

    static Animal createDog(final int size) {
        if(size > 5) {
          return new BigDog();
        }

        return new Dog();
    }
}
Enter fullscreen mode Exit fullscreen mode

Y finalmente, es interesante mencionar que este patrón ofrece las bases para el patrón service provider framework (por ejemplo usado en JDBC).

Encontramos dos desventajas principales:

  1. En el caso de usar constructores privados para usar métodos estáticos, no podremos tener subclases, porque las subclases tienen que poder llamar al constructor de la superclase.

  2. Otro problema es que son más difíciles de encontrar para los programadores, ya que dentro de la documentación de Java (Javadoc), no tienen nada que los destaque como si lo tienen los constructores.

Referencia
Joshua Bloch, Effective Java (3ª edición), Addison-Wesley, 2018.

Top comments (0)