Al modelar clases, cuál es la forma preferida de inicializar:
- Constructores, o
- Métodos de fábrica
¿Y cuáles serían las consideraciones para usar cualquiera de ellos?
En ciertas situaciones, prefiero tener un método de fábrica que devuelva nulo si el objeto no se puede construir. Esto hace que el código sea ordenado. Simplemente puedo verificar si el valor devuelto no es nulo antes de tomar una acción alternativa, en contraste con lanzar una excepción del constructor. (Personalmente no me gustan las excepciones)
Digamos que tengo un constructor en una clase que espera un valor de id. El constructor usa este valor para completar la clase desde la base de datos. En el caso de que no exista un registro con la identificación especificada, el constructor lanza una excepción RecordNotFoundException. En este caso, tendré que incluir la construcción de todas esas clases dentro de un bloque try..catch.
En contraste con esto, puedo tener un método de fábrica estático en esas clases que devolverá nulo si no se encuentra el registro.
¿Qué enfoque es mejor en este caso, constructor o método de fábrica?
Pregúntese qué son y por qué los tenemos. Ambos están allí para crear una instancia de un objeto.
No hay diferencia hasta ahora. Ahora imagine que tenemos varios tipos de escuelas y queremos cambiar de usar ElementarySchool a HighSchool (que se deriva de una ElementarySchool o implementa la misma interfaz ISchool que la ElementarySchool). El cambio de código sería:
En caso de una interfaz tendríamos:
Ahora, si tiene este código en varios lugares, puede ver que usar el método de fábrica puede ser bastante barato porque una vez que cambia el método de fábrica ya está listo (si usamos el segundo ejemplo con interfaces).
Y esta es la principal diferencia y ventaja. Cuando comienza a tratar con jerarquías de clase complejas y desea crear dinámicamente una instancia de una clase a partir de dicha jerarquía, obtiene el siguiente código. Los métodos de fábrica pueden tomar un parámetro que le dice al método qué instancia concreta se debe instanciar. Digamos que tiene una clase MyStudent y necesita crear una instancia del objeto ISchool correspondiente para que su estudiante sea miembro de esa escuela.
Ahora tiene un lugar en su aplicación que contiene la lógica de negocios que determina qué objeto de ISchool instanciar para diferentes objetos de IStudent.
Entonces, para las clases simples (objetos de valor, etc.), el constructor está bien (no desea modificar la ingeniería de su aplicación), pero para las jerarquías de clases complejas, el método de fábrica es una forma preferida.
De esta manera, sigue el primer principio de diseño de la pandilla de cuatro libros "Programa para una interfaz, no una implementación".
fuente
IFood sandwich = new Sandwich(Cheese chz, Meat meat);
yIFood soup = new Soup(Broth broth, Vegetable veg);
cómo pueden ayudar aquí la fábrica o el constructor?Debe leer (si tiene acceso a) Java 2 Elemento 1 efectivo : considere métodos de fábrica estáticos en lugar de constructores .
Ventajas de los métodos estáticos de fábrica:
Desventajas de los métodos estáticos de fábrica:
fuente
( factory methods are better than Constructors. ( Item-1 ) ) Effective java
Por defecto, los constructores deben ser preferidos, porque son más simples de entender y escribir. Sin embargo, si necesita desacoplar específicamente las sutilezas de construcción de un objeto de su significado semántico tal como lo entiende el código del cliente, sería mejor usar fábricas.
La diferencia entre constructores y fábricas es análoga a, por ejemplo, una variable y un puntero a una variable. Hay otro nivel de indirección, que es una desventaja; pero también hay otro nivel de flexibilidad, que es una ventaja. Entonces, al hacer una elección, le recomendamos que haga este análisis de costo versus beneficio.
fuente
Use una fábrica solo cuando necesite control adicional con la creación de objetos, de una manera que no se podría hacer con los constructores.
Las fábricas tienen la posibilidad de almacenar en caché, por ejemplo.
Otra forma de usar fábricas es en un escenario en el que no sabes el tipo que quieres construir. A menudo ve este tipo de uso en escenarios de fábrica de complementos, donde cada complemento debe derivar de una clase base o implementar algún tipo de interfaz. La fábrica crea instancias de clases que derivan de la clase base o que implementan la interfaz.
fuente
Una cita de "Java eficaz", 2ª ed., Ítem 1: Considere métodos de fábrica estáticos en lugar de constructores, p. 5:
"Tenga en cuenta que un método de fábrica estático no es lo mismo que el patrón de Método de fábrica de Patrones de diseño [Gamma95, p. 107]. El método de fábrica estático descrito en este elemento no tiene un equivalente directo en Patrones de diseño".
fuente
Además de "Java efectivo" (como se menciona en otra respuesta), otro libro clásico también sugiere:
P.ej. no escribas
pero en cambio escribe
El libro llega a sugerir que el
Complex(float)
constructor sea privado, para obligar al usuario a llamar al método estático de fábrica.fuente
from…
,to…
,parse…
,with…
, y así sucesivamente. Tenga en cuenta que las clases java.time están diseñadas para ser inmutables, pero algunas de estas convenciones de nomenclatura también pueden ser útiles para seguir con clases mutables.Un ejemplo concreto de una aplicación CAD / CAM.
Se haría un camino de corte utilizando un constructor. Es una serie de líneas y arcos que definen un camino para cortar. Si bien la serie de líneas y arcos puede ser diferente y tener diferentes coordenadas, se maneja fácilmente pasando una lista a un constructor.
Una forma sería hecha usando una fábrica. Porque si bien hay una clase de forma, cada forma se configurará de manera diferente según el tipo de forma que sea. No sabemos qué forma vamos a inicializar hasta que el usuario realice una selección.
fuente
Este proceso definitivamente debería estar fuera de un constructor.
El constructor no debe acceder a la base de datos.
La tarea y la razón de un constructor es inicializar miembros de datos y establecer invariantes de clase utilizando valores pasados al constructor.
Para todo lo demás, un mejor enfoque es utilizar un método de fábrica estático o, en casos más complejos, una clase de fábrica o de constructor separada .
Algunas líneas de guía del constructor de Microsoft :
Y
fuente
A veces tiene que verificar / calcular algunos valores / condiciones mientras crea un objeto. Y si puede lanzar una excepción, el constructro es muy malo. Entonces necesitas hacer algo como esto:
Donde todos los cálculos adicionales están en init (). Pero solo usted como desarrollador realmente sabe acerca de este init (). Y, por supuesto, después de meses te olvidas de eso. Pero si tiene una fábrica, solo haga todo lo que necesita en un método para ocultar este init () de la llamada directa, así que no hay problemas. Con este enfoque no hay problemas con caer en la creación y la pérdida de memoria.
Alguien te contó sobre el almacenamiento en caché. Es bueno. Pero también debe recordar el patrón Flyweight, que es agradable de usar con la forma Factory.
fuente