language-agnostic - the - sequence diagram prototype pattern
¿Dónde utilizarías un patrón de generador en lugar de una fábrica abstracta? (10)
He visto esta pregunta surgir aquí y allá varias veces, pero nunca encontré una respuesta con la que estaba feliz.
De Wikipedia:
El constructor se enfoca en construir un objeto complejo paso a paso. Abstract Factory hace hincapié en una familia de objetos de productos (simples o complejos). Builder devuelve el producto como paso final, pero en lo que respecta a Abstract Factory, el producto se devuelve inmediatamente.
Pero para el cliente, ¿no es lo mismo? Obtiene el objeto completo una vez que está construido, por lo que para él no hay ninguna funcionalidad adicional.
La única forma en que lo veo es como una forma u organizar el código del constructor en pasos, para forzar una estructura para la implementación de los constructores. Lo que está bien, pero no es un gran paso desde la fábrica abstracta.
Este próximo bit de Wikipedia es una buena referencia para llegar a mi punto:
A menudo, los diseños comienzan utilizando Factory Method (menos complicado, más personalizable, las subclases proliferan) y evolucionan hacia Abstract Factory, Prototype o Builder (más flexible, más complejo) a medida que el diseñador descubre dónde se necesita más flexibilidad.
Si es así, ¿qué tipo de complejidad tendría que introducirse en su sistema en el que cambiaría de Abstract Factory a Builder?
Mi punto es que no puedo encontrar un ejemplo donde quede claro que no basta con un Abstract Factory y que en su lugar necesitarías un Builder.
AbstractFactory es para una familia de productos relacionados. El Builder es para un producto.
El Constructor es para construir un producto complejo paso a paso, mientras que el AbstractFactory debe construir de una manera abstracta (es decir, una vez para varias implementaciones) un producto menos complejo.
Ejemplos de lo que la diferencia significa para el código de llamada:
Para el código del cliente que utiliza un AbstractFactory, cada llamada de método construye un objeto. El cliente tiene que juntarlos . En el otro lado, un constructor los ensamblaría internamente y entregaría el gráfico de objetos completo como el último paso del edificio.
El constructor permite pasar y verificar los parámetros uno por uno para el código del cliente. Pero puede construir el producto final en un solo paso (por ejemplo, una llamada a un constructor, pasando todos los parámetros a la vez, incluso los sofisticados que se han construido ellos mismos). Entonces, el producto de un constructor podría ser un objeto inmutable (o gráfico de) (que no tiene precio en un entorno de subprocesos múltiples, por razones de rendimiento y memoria).
ACTUALIZADO en respuesta a este comentario:
Lino> Todavía me está molestando, aunque :). Quiero decir, si estás construyendo objetos compuestos y sacas al director, pasando la responsabilidad de llamar a los métodos del constructor a los clientes, entonces funciona para mí. Sólo entonces el constructor parecería un ajuste perfecto. Pero con el director, no parece mucho ...
Precisamente, el Constructor no tiene director, le permite a cada cliente crear un producto complejo de acuerdo con sus necesidades específicas . El cliente es el director, porque la implementación del director no se reutiliza.
Si necesita reutilizar unas cuantas veces un proceso de construcción complejo, entonces puede tener un método para resumirlo (y este método es su "director").
Por el contrario, para AbstractFactory, normalmente necesita un Director reutilizable, que cree productos por igual (provistos con una implementación de Factory).
Algunas respuestas muy buenas aquí ya. Solo estoy ofreciendo una analogía.
Digamos que querías un nuevo escritorio para tu nueva oficina. Usted va a una ''fábrica'' y ve selecciones y luego elige uno de los estantes. Si se ajusta a tus necesidades, ¡genial!
Ahora tienes una oficina más grande con paredes con formas realmente elegantes. Ahora necesita un escritorio con la parte superior en forma para adaptarse a su oficina. Y desea unas patas diferentes para adaptarse al resto de los muebles y también para adaptarse a su nueva silla Aeron.
Vuelves a la misma fábrica, sin suerte. Usted va a un carpintero que puede "construir" lo que usted quiere. Usted da sus especificaciones y requisitos y el ''constructor'' le dirá ciertas limitaciones. Después de algunas iteraciones, tienes el escritorio perfecto!
Ok, una historia aburrida pero solo para aclarar las cosas: P
Buenas respuestas, me gustaría agregar el mío con la esperanza de que descubra que mi comprensión es correcta.
Si tiene una oficina nueva y solo necesita escritorios nuevos, usaría un Builder. Un escritorio siempre será un escritorio, pero hay muchas configuraciones diferentes para un escritorio, es decir, tamaño, forma, presencia de un aparador, cajones, etc.
Si tiene una oficina nueva y el interior está completamente vacío, necesitaría varios objetos y usaría una Abstract Factory que crea muebles, de la cual desciende nuestro Escritorio. En este caso, Desk, tal como lo conocemos, es un objeto "complejo", por lo que utiliza el patrón Builder, pero aquí forma parte de una Fábrica de Abstract abstracta. The Abstract Factory también crearía objetos simples, como lámparas muy específicas (StraightFunkyLamp), a través de una clase StraightFunkyLampFactory.
Builder es una inversión de control, como el patrón de método de plantilla. Las diversas funciones de su constructor de concreto son pasos personalizables en un proceso. Abstract Factory es un polimorfismo "justo", donde la salida resulta ser un objeto recién construido. Las diversas funciones en una fábrica de concreto son procesos personalizables diferentes, cada uno de los cuales presumiblemente resulta en un objeto diferente.
Por lo tanto, necesita un constructor cuando necesita que exista una "trama" general común para construir sus objetos, pero las "escenas" individuales dentro de esa trama son diferentes. Necesitas una fábrica cuando no hay necesariamente nada en común entre diferentes implementaciones.
Creo que posiblemente podría usar ambos a la vez, con Abstract Factory actuando como director en el patrón Builder, y cada fábrica de concreto dirigiendo las cosas de manera diferente. Sin embargo, eso va más allá del límite de "servilleta" para los diagramas UML ;-)
El constructor es útil para la configuración. Abstract Factory es útil cuando no desea que las personas que llaman se preocupen por la implementación real. Dos propósitos diferentes.
Podrías, de hecho, mezclar los dos patrones. Por ejemplo, DocumentBuilderFactory de Java es una fábrica abstracta clásica: si lees los documentos, verás el proceso que usa para elegir una implementación. Sin embargo, los DocumentBuilder que produce pueden configurarse posteriormente (aunque no siguen el enfoque prototípico de "constructor" de que cada método de configuración devuelva el objeto que se está configurando).
En la práctica, probablemente usará DI + IOC para hacer lo que un constructor solía hacer. Para tu información
Para obtener más información sobre cuándo usar el patrón de creación y sus ventajas , debe consultar mi publicación para otra pregunta similar here
Un buen ejemplo de dónde querría un constructor es si construyera algo pieza por pieza basándose en argumentos de la línea de comando. Por ejemplo, considere un constructor con métodos como ...
setName()
setType()
setOption()
Un constructor también podría combinarse con una fábrica abstracta donde el director le pide a la fábrica un producto concreto. Nuevamente, esto podría hacerse con un patrón de fábrica pasando la lista de argumentos a la fábrica, pero ¿qué pasaría si los argumentos fueran en su lugar mensajes provenientes de un servidor o un cliente?
A veces, la estética de un patrón se ajusta mejor que la estética del otro.
Utilizo un Abstract Factory cuando necesito construir varias fábricas infantiles para crear diferentes tipos de objetos. Todas estas fábricas infantiles implementan o amplían la Fábrica abstracta. Utilizo un Builder cuando solo hay un tipo de objeto que se debe construir.
No estoy seguro de si este es el uso correcto, pero es cómo lo he visto hacer y cómo lo he hecho en el pasado.
Consideremos una analogía.
Estás en una cadena de comida rápida, donde la comida rápida que obtienes es bastante compleja. No solo es complejo, sino que también ciertas personas pueden tomar su pedido de ciertos tipos de alimentos. Ahora, usted no lo sabe, porque el gerente de la tienda decidió poner a una persona detrás de una caja registradora. Pero si lo miras con cuidado, en realidad es un holograma avanzado porque es "abstracto" . Un tomador de orden abstracto. Ahora, cuando habla con el holograma y hace su pedido, la computadora del holograma redirige (polimorfismo) ese orden a un implante en el cerebro de un tomador de orden humano. El implante hace que el ser humano realmente puntee en el pedido a un registro real. Hay pocos de estos seres humanos "concretos" controlados por la mente ordenados por el holograma. Ahora, cuando el ser humano real golpea en el pedido, se envía a una computadora en la parte posterior donde hay una línea de ensamblaje, o un "constructor" , para cada tipo de alimento que se construye. Los pedidos se envían a diferentes tipos de líneas de ensamblaje según el ser humano y su caja registradora.
Entonces, el holograma es la fábrica abstracta, los humanos controlados por la mente en los registros son las fábricas de hormigón y las líneas de ensamblaje son los constructores. Esta es una manera de visualizar el flujo de una fábrica abstracta trabajando con el patrón de construcción. A veces es mejor ver cómo los patrones de diseño trabajan juntos para ver en qué se diferencian.
Si está buscando crédito adicional, intente implementarlo con genéricos. No requiere tanto código como podría pensar.