Factorias vs Constructores
Tags: java
Published: 2022-03-06 17:27:50

---
title: Factorias vs Constructores
published: true
date: 2022-02-23 07:22:42 UTC
tags: java
canonical_url: https://jorge.aguilera.soy/blog/effective-java/1-constructors.html
---

El tema de los constructores de objetos es prácticamente lo primero que se aprende cuando empiezas a usar el paradigma OOP (programación orientada a objetos).

Yo lo tuve que aprender en el paso de C a C (en el cual supongo que se inspiró luego Java y otros) y recuerdo que me explotó la cabeza cuando por fín más o menos lo entendí, teniendo en cuenta que además C permite la herencia múltiple, por lo que las llamadas entre constructores de la clase instanciada y las heredadas era todo un laberinto.

En Java el método que se llame como la clase es el constructor, y puedes tener más de uno simplemente definiendo diferentes parámetros de entrada:

```
class Oso{
    Oso(){}
    Oso(String nombre)
}
```

<dl>
<dt>INFO</dt>
<dd>
<p>"Consider static factory methods instead of constructors"</p>
</dd>
</dl>

Además de los constructores típicos, el autor propone usar métodos estáticos que sirvan para construir los objetos. Por ejemplo:

```
class Oso{
    public static Oso newInstance(String nombre){
        return new Oso(nombre);
    }
}
```

Aunque nada te obliga a seguir haciendo los constructores públicos, la propuesta es hacerlos "invisibles" al resto de clases en favor de los métodos factory. Las ventajas de esto serían:

<dl>
<dt>TIP</dt>
<dd>
<p>a diferencia del constructor (que tiene que llamarse como la clase), los métodos pueden tener nombre.
No es lo mismo "new Oso(arg0, arg1)" que "Oso.creaOsoPardoDelNorteDeAmerica()"</p>
</dd>
</dl>

Cuando el número de parámetros en el constructor no ayuda en elegir cual de ellos usar, un factory metodo sí pude hacerlo.

**Si tienes un objeto con uno o varios constructores, o si el número de parámetros para invocarlo es "grande" o "confuso", hazlos privados o mejor aún, eliminalos, y conviertélos en métodos static factory**

<dl>
<dt>TIP</dt>
<dd>
<p>otra ventaja es que a diferencia del constructor, que siempre crea un objeto nuevo, el método no tiene
porqué.</p>
</dd>
</dl>

Puedes entonces jugar con Caches o instancias construidas como static, etc que te permitan reutilizar objetos ya construidos

<dl>
<dt>TIP</dt>
<dd>
<p>no estás sujeto a devolver una instancia de esa clase, puedes devolver objetos que la extiendan, etc sin necesidad de que el que llame al método tenga que hacer casteos ni preocuparse por conversiones</p>
</dd>
<dt>TIP</dt>
<dd>
<p>flexibilidad para cambios futuros en las clases devueltas.</p>
</dd>
</dl>

Derivado del comentario anterior, si el objeto sólo se puede construir a través de metódos estáticos, puedes cambiar en una versión futura el objeto devuelto sin afectar a quien lo llama. Por ejemplo, clases que se deprecan pueden dejar de ser utilizadas cambiando simplemente el factory

<dl>
<dt>TIP</dt>
<dd>
<p>permite construir clases "al vuelo"</p>
</dd>
</dl>

Aunque parece algo "para nota", el método factory puede usar la potencia de Java y obtener la implementación a devolver en el momento en el que se le llame (por ejemplo usando `service provider framework`, descargando el jar de un repositorio remoto, etc)

<dl>
<dt>WARNING</dt>
<dd>
<p>si sólo tienes métodos static factory, la clase no puede contener subclases</p>
</dd>
<dt>WARNING</dt>
<dd>
<p>tienes que usar nombres de métodos claros que indiquen que son factoria para facilitar al
que los va a usar el encontrarlos (<code>from</code>, <code>valueOf</code>, <code>newInstance</code>, …​)</p>
</dd>
</dl>