Применяется ли оператор switch в фабричном методе? C #

13
задан Hcabnettek 29 July 2009 в 10:37
поделиться

6 ответов

I don't usually mind switch statements in a factory, provided I can group and control all of the derived classes that I want my factory to create in advance.

Sometimes,maybe a user-created plugin might want to add it's own classes to that switch list, and then a swich statement is not enough.

I found this good source for some more info on creating some more powerfull/versatile factory classes

A good middle-ground approach I usually take is to keep a static Dictionary< string,Type > for each factory class.

People can just "register" their own implementations using some sort of

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

(or better yet, use a Registration method and hide the StaticDictionary)

then the Factory has an easy task of creating an instance by performing a lookup in the table:

Activator.CreateInstance(Factories.TypeRegistration.StaticDictionary["somekey"]);
19
ответ дан 1 December 2019 в 20:11
поделиться

Я не знаю, какие возможности у вас есть в C #, но все же лучше иметь один переключатель в заводском методе, чем иметь переключатели повсюду. В заводском методе переключение допустимо, но лучше его хорошо задокументировать.

3
ответ дан 1 December 2019 в 20:11
поделиться

Я бы предпочел иметь тип, который вы хотите создать для определенного значения в файле конфигурации. Примерно так:







Внутри вашего метода вы можете затем извлечь все регистрации из файла конфигурации, найти соответствующую и использовать отражение для создания экземпляра типа, если регистрация не найдена, вы генерируете исключение.

Вот это некоторый пример кода:

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);      

    }
}

Многие инфраструктуры DI позволяют вам предоставлять несколько регистраций для интерфейса, который вы можете запрашивать на основе метаданных. Просмотрите эту ссылку о том, как MEF выполняет экспорт с использованием метаданных.

3
ответ дан 1 December 2019 в 20:11
поделиться

Я бы не сказал, что это плохой дизайн, хотя потенциально он довольно жесткий. Единственный способ расширить это - перекомпиляция.

2
ответ дан 1 December 2019 в 20:11
поделиться

Я не думаю, что в этом что-то плохое. Да, операторы switch - это запах кода, но в моей книге они подходят для подобных ситуаций. На самом деле мало что еще можно сделать для достижения подобных целей.

2
ответ дан 1 December 2019 в 20:11
поделиться

Это неплохо, это почти точно так же, как пример (параметризованный заводской метод) в самой Библии «Банды четырех».

Раньше я думал, что операторы переключения - это запах кода, их нет, у них есть свое место в любом ОО-языке.

2
ответ дан 1 December 2019 в 20:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: