2011-02-02 9 views
17

¿El patrón de fábrica de C# requiere un cambio?fábrica de C#: ¿está pendiente la actualización?

Quiero que God in class library G cree un Adam en la biblioteca A de clase sin hacer que G dependa de A. Dios produce Adams para que Eve lo consuma en la biblioteca E, y está bien que Eve sepa y dependa de Adam. (edit - esta muestra sigue mejorando :)

La solución que se me ocurre es tener una AdamFactory en A. De esta forma, AdamFactory conoce a Adam y puede crearlo fácilmente (posiblemente solo llamando al constructor de Adam). Dios recibe una AdamFactory y puede ordenarla para Create Adam.

Ahora, porque Dios no tiene permitido conocer a Adam, CreateAdam de AdamFacotry debe devolver un objeto, y esto requiere que Eve eleve el objeto devuelto por AdamFactory a un Adam.

Esto funcionará, creo. Sin embargo, me siento incómodo con el up-casting, ya que es un no-no. ¿Es esto realmente una necesidad?

P.S. - Sin Blasfemia, y me disculpo si los sentimientos de alguien fueron lastimados. Parecía mejor usar a Dios y a Adán en vez del Creador y Creado porque las dos últimas palabras son muy similares entre sí.

Editar: sugerencia de interfaces Re. Supongamos que Adam tiene dos métodos: ProvideLove, ProvideFood y ProvideProtection (mantenemos esta muestra kis-safe :). Eva usa a Adán para estos dos propósitos, pero por supuesto que Dios no. Entonces, ¿por qué darle a Dios el conocimiento de que AdamFactor devuelve algo que implementa un IAdam y no solo un objeto? ¡No lo entiendo!

Editar: El código de trabajo (con todo el mundo en la misma biblioteca, que mi objetivo es separar a las diferentes bibliotecas) se ve algo como esto:

Adam God.LoadAdam(AdamID theAdamID) 
     var adam = new Adam(theAdamId, this) 

Adam.Adam(AdamID theAdamID, God theGod) 
     _god = theGod 
     _mind = theGod.LoadMind(theAdamId, this) 

Mind God.LoadMind (AdamID theAdamID, Adam theAdam) 
     var mind = new Mind (theAdam) 
     var mindId = new minId(theAdamId) 
     mind.DeserializeFromFile(minId) 

Mind.Mind (Adam theAdam) 
     _adam = theAdam 
+2

Creo que quieres * derribar * el objeto devuelto a un Adam. –

+0

Me gustaría ir a las interfaces, como se indica en la primera respuesta. De todos modos, +1 por buena pregunta, muy divertido :-) – Shimrod

+3

Volvió a subir la pregunta de la muestra incluso antes de leerla hasta el final. :) – Stilgar

Respuesta

9

No estoy seguro de entender completamente los requisitos, pero aquí es una sugerencia:


//in assembly G 
public abstract class HumanFactory<T> 
{ 
    public abstract T CreateHuman(); 
} 

//in assembly A 
public class Adam { } 
//in assembly A 
public class AdamFactory : HumanFactory<Adam> 
{ 
    public override Adam CreateHuman() 
    { 
     return new Adam(); 
    } 
} 

//in assembly G 
public class God 
{ 
    public T Create<T>(HumanFactory<T> factory) 
    { 
     return factory.CreateHuman(); 
    } 
} 

y el uso:


//Somewhere in assembly E 
Adam adam = new God().Create(new AdamFactory()); 
+0

+1 dado el conjunto completo "Pregunta + comentarios" Diría que esta es la solución más sensata. Sin embargo, hay algo mal en el diseño de OP, en mi humilde opinión. – Simone

+0

@Simone este diseño puede tener algunos usos. Para ser útil, debe haber restricciones genéricas basadas en interfaces comunes o clases base para Adán y las otras instancias creadas por Dios.Entonces Dios puede hacer otro trabajo excepto llamando ciegamente a la Fábrica de Adán. Además, la clase base de HumanFactory puede tener métodos adicionales que Dios puede usar para hacer un trabajo adicional. – Stilgar

+0

@Simone, Dios puede hacer que Adán viva para cada uno clasificando el lado de la base de datos de las cosas, etc., Eva no puede hacer esto porque está fija en un punto sigle (pero en movimiento) en la línea de tiempo. –

1

¿Qué pasa con el uso de interfaces de modo que Dios sabe iAdam, o algo como IHuman?

+0

Dios no tiene que usar a Adán. Entonces, ¿cómo se beneficiaría Dios de la interfaz? – Avi

0

Está describiendo un abstract factory pattern, aunque las fábricas "secundarias" (por ejemplo, AdamFactory) normalmente tienen algo en común, por lo que esperaría que produjeran algo más como una interfaz común que como un objeto (ver la respuesta de Davide)

Tienes razón que preocuparse por el up-yeso ya que atará a Eva para la puesta en práctica de Adán, que contradice el objetivo de una fábrica (a menos que estés realmente usarlo como un constructor).

La pregunta es, ¿por qué necesitas la clase de Dios en absoluto?

0

Bueno, si Dios es una biblioteca de clases de persistencia como usted ha mencionado en comentar, entonces no debe influir en el diseño de la clase del resto del sistema.

Por lo tanto, no agregaría interfaces innecesarias. Está bien devolver un objeto del deserializador y un downcast después (p.BinaryFormatter, XmlSerializer).

La mejor manera sería hacer su deserializador genérico.

0

OK, ¿qué hay de rociar en algunos genéricos aquí?

Digamos que Dios pueda aceptar fábricas de cualquier tipo T que se adhieren a la siguiente interfaz:

interface IFactory { 
    Type CreatedType { get; } 
    object Create(); 
} 

Una clase abstracta para implementar esta puede tener este aspecto:

abstract class AbstractFactory<T> : IFactory { 
    public Type CreatedType { get { return typeof(T); } 
    public virtual object Create() { 
    return innerCreate(); 
    } 
    protected abstract override T innerCreate(); 
} 

Ahora, se puede registrar fábricas con Dios:

God.RegisterFactory(new AdamFactory()); 

AdamFactory hereda de AbstractFactory<Adam>

Dios almacena sus fábricas en un diccionario donde la clave es el tipo devuelto por la interfaz IFactory

el Método Crear ahora se ve así:

God.Create<Adam>(); 

Dios mira en sus fábricas, ve allí es uno para typeof (T) del método genérico, recupera la fábrica, llama a create y downcasts a T.

¿Qué opinas?

+1

Pero entonces casi está comenzando a construir un contenedor de IoC. Ciertamente, Dios es un buen nombre para un contenedor de IoC, pero ya hay un par de ellos alrededor. – flq

+0

Dios tal vez más de un contenedor de servicio ... – DaeMoohn

Cuestiones relacionadas