que patron method ejemplo diseño c# design-patterns interface factory-method

c# - patron - ¿Es aplicable una declaración de cambio en un método de fábrica? do#



patron de diseño abstract factory c# ejemplo (6)

No creo que haya nada de malo en esto. Sí, las declaraciones de cambio son un olor a código, pero en mi libro, están bien en este tipo de situación. En realidad, hay poco más que podrías hacer para lograr cosas como esta.

Quiero devolver una interfaz y dentro de una declaración de cambio me gustaría configurarlo. ¿Es este un mal diseño?

private IResultEntity GetEntity(char? someType) { IResultEntity entity = null; switch (someType) { case ''L'': //life entity = new LifeEntity(); break; case ''P'': //property entity = new PropertyEntity(); break; case ''D'': //disability entity = new DisabilityEntity(); break; case ''C'': //credit card entity = new CreditCardEntity(); break; } return entity; }


No diría que es un mal diseño, aunque es potencialmente bastante rígido. La única forma de extender esto sería a través de la recompilación.


No sé, qué posibilidades tienes en c #, pero aún es mejor tener un interruptor en un método de fábrica que tener interruptores por todos lados. En un método de fábrica, un interruptor es tolerable, pero es mejor que esté bien documentado.


Prefiero tener el tipo que desea instanciar para un valor específico en un archivo de configuración. Algo como:

<TypeMappings>
<TypeMapping name = "life" type = "Entities.LifeEntity, Entities" />
<TypeMapping name = "property" type = "Entities.PropertyEntity, Entities" />
<TypeMapping name = "disability" type = "Entities.DisabilityEntity, Entities" />
<TypeMapping name = "creditcard" type = "Entities.CreditCardEntity, Entities" />
</ TypeMappings>

Dentro de su método, puede extraer todos los registros del archivo de configuración, encontrar el que coincida y usar el reflejo para crear una instancia del tipo; si no se encuentra el registro, arroja una excepción.

Aquí hay un código de muestra:

namespace Entities { public interface IResultEntity { } public class LifeEntity : IResultEntity { public override string ToString() { return("I''m a Life entity"); } } public class PropertyEntity : IResultEntity { public override string ToString() { return("I''m a Property Entity"); } } public class CreditCardEntity : IResultEntity { public override string ToString() { return("I''m a CreditCard Entity "); } } public class DisabilityEntity : IResultEntity { public override string ToString() { return("I''m a Disability Entity"); } }

}

public static Entities.IResultEntity GetEntity(string entityTypeName,string fileName) { XDocument doc = XDocument.Load(fileName); XElement element = doc.Element("TypeMappings").Elements("TypeMapping") .SingleOrDefault(x => x.Attribute("name").Value == entityTypeName); if(element == null) { throw new InvalidOperationException("No type mapping found for " + entityTypeName); } string typeName = element.Attribute("type").Value; Type type = Type.GetType(typeName); Entities.IResultEntity resultEntity = Activator.CreateInstance(type) as Entities.IResultEntity; if(resultEntity == null) { throw new InvalidOperationException("type mapping for " + entityTypeName + " is invalid"); } return resultEntity; } public static void Main() { try { Entities.IResultEntity result = GetEntity("life", @"c:/temp/entities.xml"); Console.WriteLine(result); result = GetEntity("property", @"c:/temp/entities.xml"); Console.WriteLine(result); result = GetEntity("disability", @"c:/temp/entities.xml"); Console.WriteLine(result); result = GetEntity("creditcard", @"c:/temp/entities.xml"); Console.WriteLine(result); result = GetEntity("foo", @"c:/temp/entities.xml"); Console.WriteLine(result); } }

Una gran cantidad de marcos DI le permiten proporcionar múltiples registros para una interfaz que puede consultar en función de los metadatos. Consulte este enlace sobre cómo MEF exporta usando metadatos.


No está mal, es casi exactamente lo mismo que un ejemplo (Método de fábrica parametrizado) en la Biblia de la Banda de los Cuatro.

Solía ​​pensar que las declaraciones de cambio son un olor a código, no lo son, tienen su lugar en cualquier lenguaje OO.


Normalmente no me importa cambiar las declaraciones en una fábrica, siempre que pueda agrupar y controlar todas las clases derivadas que quiero que mi fábrica cree con anticipación.

A veces, tal vez un complemento creado por el usuario podría querer agregar sus propias clases a esa lista de conmutadores, y luego una declaración swich no es suficiente.

Encontré esta buena fuente para obtener más información sobre cómo crear algunas clases de fábrica más potentes y versátiles

Un buen enfoque intermedio que suelo adoptar es mantener un Dictionary <string, Type> estático para cada clase de fábrica.

La gente puede simplemente "registrar" sus propias implementaciones usando algún tipo de

Factories.TypeRegistration.StaticDictionary.Add("somekey",typeof(MyDerivedClass))

(o mejor aún, use un método de registro y oculte el StaticDictionary)

luego Factory tiene una tarea fácil de crear una instancia realizando una búsqueda en la tabla:

Activator.CreateInstance(Factories.TypeRegistration.StaticDictionary["somekey"]);