Pregunta

Una de las maneras de aplicar la Inyección de Dependencia correctamente es separar la creación de objetos a partir de la lógica de negocio.Normalmente, esto implica el uso de una Fábrica para la creación de objetos.

Hasta este punto, nunca he considerado seriamente el uso de una Fábrica, así que pido disculpas si esta pregunta parece un poco simplista:

En todos los ejemplos de la Fábrica Patrón que me he encontrado de todo, yo siempre veo ejemplos muy simples que no tienen la parametrización.Por ejemplo, he aquí una Fábrica de robo de Misko Hevery del excelente Cómo Pensar el Operador "new" artículo.

class ApplicationBuilder {
  House build() {
    return new House(new Kitchen(
               new Sink(),
               new Dishwasher(),
               new Refrigerator())
           );
  }
}

Sin embargo, ¿qué sucede si quiero que cada casa que voy a construir para tener un nombre?Estoy usando todavía el patrón de Fábrica si me re-escribir el código de la siguiente manera?

class ApplicationBuilder {
  House build( const std::string & house_name) {
    return new House( house_name,
                      new Kitchen(new Sink(),
                                  new Dishwasher(),
                                  new Refrigerator())
                    );
  }
}

Tenga en cuenta que mi Fábrica llamada al método ha cambiado de esto:

ApplicationBuilder builder;
House * my_house = builder.build();

A este:

ApplicationBuilder builder;
House * my_house = builder.build("Michaels-Treehouse");

Por el camino:Creo que el concepto de separar el objeto de crear instancias de la lógica de negocios es grande, sólo estoy tratando de averiguar cómo lo puedo aplicar a mi propia situación.Lo que me confunde es que en todos los ejemplos que he visto de el patrón de Fábrica nunca pasar parámetros a la función build ().

Para ser claros:No sé el nombre de la casa hasta el momento antes de que la necesidad de crear instancias de ella.

¿Fue útil?

Solución

He visto muchos ejemplos que utilizan un conjunto fijo de argumentos, como en el ejemplo de nombre, y los he utilizado a mí también y yo no le veo nada de malo.

Sin embargo, hay una buena razón por la que muchos de los tutoriales o artículos pequeños evitar que se muestren las fábricas que los parámetros de los objetos construidos:Es prácticamente imposible avanzar número arbitrario de argumentos (incluso para una sana límite como 6 argumentos).Cada parámetro que adelante tiene que ser aceptada como const T& y T& si quieres hacerlo de genéricos.

Para obtener más complicado ejemplos, sin embargo, se necesita un aumento exponencial de la serie de sobrecargas (para cada parámetro, una constante y una nonconst versión) y perfecto reenvío no es posible (de modo que los empleos temporales son transmitidos como temporales, por ejemplo).Para el próximo Estándar de C++ que el problema está resuelto:

class ApplicationBuilder {
  template<typename... T>
  House *build( T&&... t ) {
    return new House( std::forward<T>(t)...,
                      new Kitchen(new Sink(),
                                  new Dishwasher(),
                                  new Refrigerator())
                    );
  }
};

De esa manera, usted puede llamar a

builder.build("Hello", 13);

Y volverá

new House("Hello", 13, new Kitchen(new Sink(...

Lee el artículo que he enlazado más arriba.

Otros consejos

No puedo ver por qué sería incorrecto agregar este parámetro a su fábrica. Pero tenga en cuenta que no debería terminar agregando muchos parámetros que podrían no ser útiles para todos los objetos creados por la fábrica. ¡Si lo hace, habrá perdido muchas de las ventajas de una fábrica!

No solo es aceptable, sino que es común pasar parámetros a un método de fábrica. Consulte algunos ejemplos . Normalmente, el parámetro es un tipo que le dice a la fábrica qué hacer, pero no hay razón para que no pueda agregar otra información que necesita para construir un objeto. Creo que lo que estás haciendo está bien.

La idea de una fábrica es que le da una instancia de una clase / interfaz, por lo que no hay nada de malo en pasar parámetros. Si lo hubiera, sería malo pasar los parámetros a un nuevo () también.

Estoy de acuerdo con Benoit. Sin embargo, piense en una fábrica para crear algo así como conexiones sql, en un caso como este sería necesario pasar información sobre la conexión a la fábrica. La fábrica usará esa información para usar el protocolo de servidor correcto, etc.

Claro, ¿por qué no ...?

Lo bueno de pasar parámetros es que le permite ocultar la implementación del objeto concreto. Por ejemplo, en el código que publicó, pasa los parámetros al constructor. Sin embargo, puede cambiar la implementación para que se pasen a través de un método Initiailze . Al pasar los parámetros al método de fábrica, oculta la naturaleza de la construcción e inicialización del objeto de la persona que llama.

Echa un vistazo a Loki :: Factory, sin embargo, hay una implementación muy parecida a la de Boost. Algún código de ejemplo que uso regularmente en diferentes sabores:

typedef Loki :: SingletonHolder < Loki :: Factory & Lt; Componente, std :: string, Loki :: Typelist & Lt; const DataCollection & amp ;, Loki :: Typelist < Juego *, Loki :: NullType & Gt; > > > ComponentFactory;

Esto puede parecer un poco extraño a primera vista, sin embargo, permíteme explicarte esta bestia y lo poderoso que realmente es. Básicamente, creamos un singleton que tiene una fábrica, la mayoría de los parámetros son para el singleton, Component es nuestro producto, std :: string es nuestro tipo de id de creación, después de esto sigue una lista de tipos de parámetros necesarios para la creación de componentes (esto se puede definir usando una macro también para una sintaxis menos detallada). Después de esta línea, uno puede hacer:

ComponentFactory :: Instance (). CreateObject (" someStringAssociatedWithConcreteType " ;, anDataCollection, aGamePointer);

Para crear objetos, para registrar uno solo use ComponentFactory :: Instance (). Register () ;. Hay un gran capítulo sobre los detalles en el libro Modern C ++ Design.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top