oop - oose - object oriented analysis and design pdf
Constructores vs métodos de fábrica (9)
Diga, tengo un constructor en una clase que espera un valor de identificación. El constructor usa este valor para poblar la clase de la base de datos.
Este proceso definitivamente debe estar fuera de un constructor.
Constructor no debe acceder a la base de datos.
La tarea y el motivo de un constructor es inicializar los miembros de datos y establecer invariante 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 fábrica o una clase de constructor por separado.
Algunas líneas de guía de constructor de Microsoft :
Haz un trabajo mínimo en el constructor. Los constructores no deberían hacer mucho más trabajo que capturar los parámetros del constructor. El costo de cualquier otro procesamiento debe retrasarse hasta que se requiera.
Y
Considere usar un método de fábrica estático en lugar de un constructor si la semántica de la operación deseada no se asigna directamente a la construcción de una nueva instancia.
Al modelar clases, ¿cuál es la forma preferida de inicialización?
- Constructores, o
- Métodos de fábrica
¿Y cuáles serían las consideraciones para usar alguno 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 claro. Simplemente puedo verificar si el valor devuelto no es nulo antes de tomar una acción alternativa, en contraste con lanzar una excepción desde el constructor. (Personalmente no me gustan las excepciones)
Diga, tengo un constructor en una clase que espera un valor de identificación. El constructor usa este valor para poblar la clase de la base de datos. En el caso en que no exista un registro con el ID especificado, el constructor arroja una RecordNotFoundException. En este caso, tendré que adjuntar 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?
Desde la página 108 de Patrones de diseño: Elementos del software reutilizable orientado a objetos por Gamma, Helm, Johnson y Vlissides.
Use el patrón de Método de fábrica cuando
- una clase no puede anticipar la clase de objetos que debe crear
- una clase quiere que sus subclases especifiquen los objetos que crea
- las clases delegan la responsabilidad en una de varias subclases auxiliares, y desea localizar el conocimiento de qué subclase auxiliar es la delegada
En ocasiones, debe verificar / calcular algunos valores / condiciones al crear un objeto. Y si puede lanzar una Excepción - constructro es una muy mala manera. Entonces necesitas hacer algo como esto:
var value = new Instance(1, 2).init()
public function init() {
try {
doSome()
}
catch (e) {
soAnotherSome()
}
}
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 simplemente te olvidas de eso. Pero si tiene una fábrica, simplemente haga todo lo que necesita en un método para ocultar este init () de la llamada directa, por lo que no hay problemas. Con este enfoque no hay problemas con la caída en la creación y la pérdida de memoria.
Alguien te dijo sobre el almacenamiento en caché. Es bueno. Pero también debe recordar el patrón Flyweight, que es agradable de usar con Factory way.
Necesita leer (si tiene acceso) Effective Java 2 Item 1: Considere métodos de fábrica estáticos en lugar de constructores .
Ventajas de los métodos estáticos de fábrica:
- Ellos tienen nombres.
- No están obligados a crear un nuevo objeto cada vez que se invocan.
- Pueden devolver un objeto de cualquier subtipo de su tipo de devolución.
- Reducen la verbosidad de crear instancias de tipo parametrizadas.
Desventajas de métodos estáticos de fábrica:
- Cuando se proporcionan solo métodos de fábrica estáticos, las clases sin constructores públicos o protegidos no se pueden subclasificar.
- No son fácilmente distinguibles de otros métodos estáticos
Por defecto, los constructores deberían ser preferidos, porque son más fáciles de entender y escribir. Sin embargo, si necesita desvincular 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 que utilice 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. Por lo tanto, al hacer una elección, se recomienda realizar este análisis de costo versus beneficio.
Pregúntate qué son y por qué los tenemos. Ambos están allí para crear una instancia de un objeto.
ElementarySchool school = new ElementarySchool();
ElementarySchool school = SchoolFactory.Construct(); // new ElementarySchool() inside
No hay diferencia hasta el momento. Ahora imagina que tenemos varios tipos de escuelas y queremos cambiar de Elementary School a HighSchool (que se deriva de Elementary School o implementa la misma interfaz de ISchool que Elementary School). El cambio de código sería:
HighSchool school = new HighSchool();
HighSchool school = SchoolFactory.Construct(); // new HighSchool() inside
En el caso de una interfaz, tendríamos:
ISchool school = new HighSchool();
ISchool school = SchoolFactory.Construct(); // new HighSchool() inside
Ahora, si tienes este código en varios lugares, puedes ver que usar el método de fábrica puede ser bastante barato porque una vez que cambias el método de fábrica, terminas (si usamos el segundo ejemplo con interfaces).
Y esta es la principal diferencia y ventaja. Cuando comienza a tratar con una jerarquía de clases complejas y desea crear dinámicamente una instancia de una clase desde dicha jerarquía, obtiene el siguiente código. Los métodos de fábrica pueden tomar un parámetro que indique al método qué instancia concreta crear. Supongamos que tiene una clase MyStudent y necesita crear una instancia del objeto ISchool correspondiente para que su alumno sea miembro de esa escuela.
ISchool school = SchoolFactory.ConstructForStudent(myStudent);
Ahora tiene un lugar en su aplicación que contiene lógica comercial que determina qué objeto ISchool crear para diferentes objetos IStudent.
Entonces, para las clases simples (objetos de valor, etc.) el constructor está bien (no desea sobre-diseñar su aplicación) pero para las jerarquías de clases complejas, el método de fábrica es una forma preferida.
De esta manera, usted sigue el primer principio de diseño de la pandilla de cuatro libros "Programa a una interfaz, no a una implementación".
Un ejemplo concreto de una aplicación CAD / CAM.
Se haría una ruta de corte usando 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 se haría mediante el uso de una fábrica. Porque si bien hay una clase de forma, cada forma se configuraría de manera diferente según el tipo de forma que sea. No sabemos qué forma vamos a inicializar hasta que el usuario haga una selección.
Una cita de "Effective Java", 2nd ed., Item 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 el 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 artículo no tiene equivalente directo en Patrones de diseño".
Use una fábrica solo cuando necesite control adicional con la creación de objetos, de una manera que no podría hacerse 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 donde no se conoce el tipo que se quiere construir. A menudo se 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 se derivan de la clase base o que implementan la interfaz.