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();
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);
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);
}
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!");
}
}
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();
}
}
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:
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.
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)