¿Por qué el patrón de diseño del método de fábrica es más útil que tener clases y llamarlas individualmente?

32

De los patrones de diseño "Gang of Four", está el método Factory:

class Factory(product)
  case product
  when a
    new A
  when b
    new B
  when c
    new C
end

new Factory(a)

¿Por qué es esto más útil que tener tres clases, a, b, y cy llamar a ellos de forma individual?

alt
fuente
1
¿Qué quieres decir exactamente? ¿Por qué no instanciar los tres? ¿Es eso lo que quieres decir?
Neil
1
@Neil No, en el patrón de fábrica todas las clases existen como hermanos. ¿Por qué llamar a la fábrica para acceder indirectamente a las clases a, b, c?
alt
3
En realidad, esto no me parece el patrón del método de fábrica, si algo está más cerca de la fábrica abstracta
jk.
2
Porque en tiempo de diseño no sabes cuál de las 3 clases necesitas instanciar.
MrWhite
2
@jk: No, realmente no lo hace. programmers.stackexchange.com/questions/81838/…
pdr

Respuestas:

54

Porque tu ejemplo no es lo suficientemente complicado. Para un escenario tan simple, ni siquiera tiene sentido usar un patrón avanzado.

Pero si tiene que saber más que el producto para construir A, B o C, y no puede tener acceso directo a ese conocimiento, entonces es útil. Entonces está utilizando la fábrica para actuar como un centro de conocimiento para producir los objetos necesarios.

Tal vez esos objetos necesitan una referencia a algún objeto X, que la fábrica puede proporcionar, pero su código en el lugar donde desea construir A, B o C no puede o no debe tener acceso a X. Tal vez cuando tenga X creas A y B pero si tienes el tipo Y, entonces creas C.

También considere que algunos objetos pueden necesitar 20 dependencias para crear; ¿entonces que? Ir a buscar esas dependencias en un lugar donde no deberían ser accesibles puede ser problemático.

Mateusz
fuente
13
+1 para dejar en claro que el patrón Factory no siempre es el mejor enfoque.
Neil
1
Porque tu ejemplo no es lo suficientemente complicado. Para un escenario tan simple, ni siquiera tiene sentido usar un patrón avanzado. Entonces, ¿qué harías en este caso? ¿Inline la construcción condicional?
pdr
Puede ser solo un método que toma el producto y devuelve lo que necesita para que sea reutilizable, por lo que no tiene que estar en línea. Si dicho método se convierte en algo más grande, o se usa en varias otras clases, puede refactorizarlo a una clase diferente.
Mateusz
El patrón se llama Método de fábrica por una razón. El método no tiene que estar en una clase diferente para ser un Método de Fábrica (aunque a menudo lo es).
pdr
He echado de menos el "Método", así que tiene razón señor.
Mateusz
23

Un patrón de fábrica suele ser más complejo que eso. Una fábrica decide sobre ciertos criterios qué instancia crear / devolver. En cambio, cuando no usa la fábrica, tendría que usar ese código repetidamente en varias ubicaciones en su código.

Como ejemplo, considere lo siguiente: necesita cargar datos desde una base de datos, pero tiene una base de datos central para la integración con muchos datos, y una más pequeña en la memoria en cada PC de desarrollo. En su código, le pide a una fábrica que obtenga un identificador de DB y la fábrica devuelve uno de ellos dependiendo, por ejemplo, de un archivo de configuración.

Andy
fuente
20

El patrón Método de fábrica abstrae el proceso de toma de decisiones de la clase que llama. Esto tiene varias ventajas:

Reutilizar. Si quiero crear instancias en muchos lugares, no tengo que repetir mi condición, así que cuando vengo a agregar una nueva clase, no corro el riesgo de perderme una.

Capacidad de prueba de la unidad. Puedo escribir 3 pruebas para la fábrica, para asegurarme de que devuelve los tipos correctos en las condiciones correctas, entonces mi clase de llamada solo necesita ser probada para ver si llama a la fábrica y luego los métodos requeridos en la clase devuelta. No necesita saber nada sobre la implementación de la propia fábrica o las clases concretas.

Extensibilidad. Cuando alguien decide que necesitamos agregar una nueva clase D a esta fábrica, ninguno de los códigos de llamada, ni las pruebas unitarias o la implementación, necesitan ser informados. Simplemente creamos una nueva clase D y ampliamos nuestro método de fábrica. Esta es la definición misma del Principio Abierto-Cerrado .

Incluso puede crear una nueva clase de fábrica y hacer que sean intercambiables en caliente, si la situación lo requiere, por ejemplo, si desea poder activar y desactivar la clase D, durante la prueba. Me he encontrado con esta situación solo una vez, pero fue extremadamente útil.

Como se ha dicho, el patrón de fábrica no siempre es el camino a seguir. Pero, donde sea que veas una instanciación condicional, debes pensarlo un momento.

pdr
fuente
14

Las ventajas clave del patrón Factory son dobles:

  1. Los lugares que necesitan una implementación del producto no necesitan saber cómo construir uno. La fábrica tiene esa información.

    ¿Quieres saber qué argumentos pasar al constructor particular? ¿O qué dependencias tienes que inyectar? ¿O cómo registrar la clase de implementación con la base de datos después de que esté completamente configurada? ¿No? Deje que la fábrica se ocupe de todo eso.

  2. Los lugares que necesitan una implementación del producto no necesitan saber en el momento de la descripción del módulo (es decir, en el momento de la compilación) cuál es el nombre de la clase de implementación.

    Por lo tanto, ano necesita tener nada que ver con A; el "qué construir" se puede describir en términos de las propiedades no funcionales deseadas, y no solo el nombre. Esto es mucho más flexible.

La desventaja es que donde sabes qué hacer y cómo hacerlo, obtienes más complejidad cuando usas una fábrica. Sin embargo, la solución es simple: ¡no use una fábrica cuando no tiene sentido!

Compañeros de Donal
fuente
2

Me gustaría pensar en los patrones de diseño en términos de que las clases son como 'personas', y los patrones son formas en que las personas se hablan entre sí.

Entonces, para mí, el patrón de fábrica es como una agencia de contratación. Tienes a alguien que necesitará un número variable de trabajadores. Es posible que esta persona conozca la información que necesita sobre las personas que contrata, pero eso es todo.

Entonces, cuando necesitan un nuevo empleado, llaman a la agencia de contratación y les dicen lo que necesitan. Ahora, para contratar a alguien, necesita saber muchas cosas: beneficios, verificación de elegibilidad, etc. Pero la persona que contrata no necesita saber nada de esto: la agencia de contratación se encarga de todo eso.

Del mismo modo, el uso de una Fábrica permite al consumidor crear nuevos objetos sin tener que conocer los detalles de cómo se crean o cuáles son sus dependencias, solo tienen que proporcionar la información que realmente desean.

Cortesía

Premraj
fuente
1

El patrón Factory es el patrón de diseño más usado y abusado.

Me he encontrado con numerosos casos en los que una clase Factory está codificada cuando un constructor simple sería adecuado.

No use una clase de fábrica a menos que: -

  • Depende de un recurso externo pero aún no sabe exactamente cuál.
  • La construcción es costosa y desea construir una vez y reutilizar muchas veces.
  • La construcción de una nueva instancia depende de las instancias que ya se han construido (por ejemplo, Su solo puede tener cinco conexiones, o debe usar un número de identificación de conexión uno más que el último número utilizado).
James Anderson
fuente
0

Use el Método de Fábrica al crear instancias de una subclase y no se supone que el código del cliente sea responsable de decidir qué subclase particular se instancia.

Es útil porque evita que tenga que cambiar el código del cliente cuando necesita cambiar qué clase se instancia. Cambiar el código existente es una mala práctica porque generalmente es propenso a errores.

Un ejemplo sería tener subclases, donde cada una ordena los datos en orden ascendente, pero de una manera diferente. Cada forma es óptima para un tipo particular de datos. por ejemplo: datos parcialmente ordenados, datos que son números, etc. El código del cliente es una clase que solo maneja la impresión de datos. Tener un código que decida qué clase de clasificación se instancia en la clase del cliente la convertiría en una clase compleja. En otras palabras, tener más de una responsabilidad, en este caso, decidir qué clase de clasificación es óptima e imprimir datos. Al poner el código que decide qué clase de clasificación se instancia en una clase Factory, separa las preocupaciones para que no necesite cambiar la clase de cliente cada vez que necesite cambiar qué clase de subclase de clasificación se instancia.

Es una forma de cubrirse el trasero, si puede prever sus cambios de fabricación propia en el futuro en cómo o en qué clase se instancia, las clases de fábrica tienen sentido para usar. Ayuda a mantener sus clases enfocadas en su única responsabilidad y, como resultado, garantiza que sea menos probable que tenga que modificar el código existente que no está relacionado.

kiwicomb123
fuente