2009-01-28 13 views
11

¿Cuál es su umbral para usar fábrica en lugar de un constructor para crear un objeto?¿Cuál es su umbral para usar fábrica en lugar de un constructor para crear un objeto?

  1. Siempre utiliza la fábrica.
  2. Usted usa fábricas solo si tiene verificaciones invariables además de verificar nulos.
  3. Siempre usa constructores
  4. Raramente utiliza fábricas ... ¿cuáles son esos casos?

pros y los contras

Actualización: Estoy solicitando patrón de la fábrica de dominio determinadas por el diseño en mi proyecto. Y una de las razones detrás de la creación de fábricas es reducir el ruido en el modelo de dominio.

Gracias

Respuesta

1

me gusta mantener el número de constructores a un bajo nivel razonable; más de dos o tres, y me pregunto qué tan bien está diseñada la construcción del objeto.

En los casos en los que se están introduciendo constructores adicionales para apoyar el establecimiento de varios atributos opcionales, me gusta usar un Builder, como se describe en Effective Java (Joshua Bloch, segunda ed.)

0

trato de medir entre aquellos . Creo que debería usar fábricas cuando:

  1. Número alto de param.
  2. Parámetro opcional. (Ambos usan el patrón Builder de la clase interna)
  3. Deberá cambiar el orden de los parámetros para realizar otras acciones, debido a los mismos tipos de parámetros pero diferentes datos.
  4. Se necesita una clase Singleton (mejor hecho con enumeración)

Con fábricas, en este caso, se puede dar un nombre propio para el estado del objeto de ser devuelto.

2

no exactamente seguro de cómo se eligió sus umbrales ...

fábricas sean apropiados si no desea el consumidor abstracta del objeto a partir de la construcción. Instancias en las que esto puede ser pertinente:

  • Es posible que desee subcontratar la implementación en tiempo de ejecución. A menudo, esto se combina con el uso de interfaces en lugar de clases concretas. Un ejemplo en Java sería cómo obtienes un objeto de documento desde un DocumentBuilder en Java.
  • Es posible que desee limitar el n. ° de instancias de un objeto. Piense en construir un Pool con un número limitado de objetos de subprocesos en lugar de solo crear nuevos todo el tiempo

Consulte el libro de patrones del Libro de los Cuatro (Gamma et al.) Y observe el patrón de fábrica en detalle para más información sobre cuándo usar este patrón.

13

Uso una fábrica si tengo una clase base abstracta (o una interfaz), y varias clases derivadas concretas, y hay alguna lógica según la cual se crea una de las clases concretas. Implemento esa lógica en la fábrica.

+3

El objetivo de una fábrica es separar la creación de objetos del cliente, y como tal, no hay nada de malo en una relación 1: 1 entre las clases concretas y las clases abstractas en un patrón de fábrica. – devlord

+1

@lorddev Sí, pero YAGNI. Cuando realmente lo necesita, puede usar el patrón de fábrica. – inf3rno

5

El caso más obvio para una fábrica es cuando la clase específica que implementa una interfaz se elegirá en tiempo de ejecución, por ejemplo, desde un archivo de configuración. No hago un uso intensivo de las fábricas, pero cuando quiero que dos objetos estén muy desacoplados, es más probable que use una fábrica para obtener una instancia de la otra.

0

Use una fábrica cuando la decisión de qué clase concreta instanciar no corresponde al cliente. p.ej. donde hay varias "familias" de objetos y la elección de qué familia usar se hace en otra parte.

3

Algo interesante acerca de C# que se relaciona con este tema, es que la nueva restricción() en los tipos genéricos que se especifican en una definición de clase obliga a los tipos gestionados por el tipo de contenedor genérico a implementar un constructor sin parámetros. La restricción new() solo es necesaria cuando se pretende crear una instancia de tipo T, como en GenericType<T>, dentro de la clase. Me parece que esto es explícitamente en apoyo de las fábricas de clase, especialmente las fábricas que producen tipos genéricos.

Para activar este requisito en su cabeza, Windows Communication Foundation (WCF) tiene una clase ChannelFactory que define el siguiente método de fábrica estática:

public static TChannel CreateChannel(Binding binding, EndpointAddress endpointAddress, Uri via) 
{ 
    ChannelFactory<TChannel> factory = new ChannelFactory<TChannel>(binding); 
    if (factory.HasDuplexOperations()) 
    { 
     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString("SFxInvalidStaticOverloadCalledForDuplexChannelFactory1", new object[] { factory.channelType.Name }))); 
    } 
    TChannel channel = factory.CreateChannel(endpointAddress, via); 
    ChannelFactory<TChannel>.SetFactoryToAutoClose(channel); 
    return channel; 
} 

Si nos fijamos en el reflector en el desmontaje de clase (Sistema. ServiceModel assembly & System.ServiceModel.Channels namespace), notará que "new()" no se usa como restricción.

Eso es porque el método utiliza CreateChannel typeof (TChannel) delegar la creación del objeto más abajo en la cadena ...

public virtual TChannel CreateChannel(EndpointAddress address, Uri via) 
{ 
    TChannel local; 
    bool traceOpenAndClose = base.TraceOpenAndClose; 
    try 
    { 
     using (ServiceModelActivity activity = (DiagnosticUtility.ShouldUseActivity && base.TraceOpenAndClose) ? ServiceModelActivity.CreateBoundedActivity() : null) 
     { 
      if (DiagnosticUtility.ShouldUseActivity) 
      { 
       ServiceModelActivity.Start(activity, this.OpenActivityName, this.OpenActivityType); 
       base.TraceOpenAndClose = false; 
      } 
      if (address == null) 
      { 
       throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address"); 
      } 
      if (base.HasDuplexOperations()) 
      { 
       throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString("SFxCreateNonDuplexChannel1", new object[] { base.Endpoint.Contract.Name }))); 
      } 
      base.EnsureOpened(); 
      local = (TChannel) this.ServiceChannelFactory.CreateChannel(typeof(TChannel), address, via); 
     } 
    } 
    finally 
    { 
     base.TraceOpenAndClose = traceOpenAndClose; 
    } 
    return local; 
} 

Puede seguir la cadena de delegación de varios niveles más profundos como se está pasando la clase Tipo hacia abajo hasta el siguiente método se llama finalmente:

RemotingServices.CreateTransparentProxy(this, classToProxy, stub, stubData); 

es extremadamente complicado, pero es la fábrica más complicada que he visto. Curiosamente, todas las maquinaciones terminan con WCF creando una clase RealProxy desde el espacio de nombres System.Runtime.Remoting.Proxies.

En conclusión, las fábricas son para objetos que tienen mucha complejidad o necesitan beneficiarse de la construcción de tipo dinámico.

0

Creo que está confundiendo el patrón del generador y el patrón de fábrica. Sugeriría simplemente usar constructores y terminar con eso. Parece que (sin ver el código) estás pensando demasiado o analizando en exceso tu código un poco.

2

Aquí es un pensamiento radical (No estoy abogando por él, pero yo no creo que dañaría):

Siempre usa métodos de fábrica!

Los métodos de fábrica son más flexibles, por ejemplo, pueden almacenar en caché los resultados o devolver clases secundarias.

Así, en lugar de:

class SomeClass { 
    public SomeClass(/*parameters*/) { /*...*/ } 
} 

Usar siempre:

class SomeClass { 
    protected SomeClass(/*parameters*/) { /*...*/ } 
    public static SomeClass New(/*parameters*/) { 
    return new SomeClass(/*parameters*/); 
    } 
} 

Los códigos de llamada de cambios:

SomeClass sc = new SomeClass(); 

Para:

SomeClass sc = SomeClass.New(); 

Ahora puede cambiar su lógica de "constructor" para devolver subclases o instancias en caché, y todas las personas que llaman no se verán afectadas. Ahora controlas el valor de retorno de tus "constructores".

Cuestiones relacionadas