Лучший способ передать параметры в класс фабрики?


Поэтому у меня есть ряд объектов, которые я назвал Impl1, Impl2, и Impl3. Каждый из них реализован интерфейс, называемый IImpl. У меня есть фабрика класса, которые поставили перед собой цель получить ImplX, который подходит для конкретной ситуации, и передавать ее своим абонентам. Поэтому код на фабрике выглядит следующим образом:

public IImpl GetInstance(params object[] args)
{
    if (args[0]=="Some Value")
         return new IImpl1();
    else if (args[0]=="Other Value")
         return new IImpl2(args[1]);
    else
         return new IImpl3(args[1]);
}

Поэтому в зависимости от аргументов, передаваемых в, выбрали разные экземпляры. Все хорошо и работает нормально. Сейчас проблема в том, что у меня есть класс, который должен вызвать этот метод фабрики. В нем нет ссылок на IImplX, что хорошо, но ветер до того, чтобы точно знать, как устроена входного массива Деыпзьапсе, для того, чтобы убедиться, что он получает правильный вид экземпляра. Код ветров выглядеть как:

switch (_selectedInputEnum)
{
    case InputType.A:
        myIImplInst = Factory.GetInstance("Some Value");
    case InputType.B:
        myIImplInst = Factory.GetInstance("Other Value",this.CollectionB);
    case InputType.C:
        myIImplInst = Factory.GetInstance("Third Value",this.CollectionC);
}

Это выглядит очень избыточно, и как-то выключить. Что бы быть лучший способ абстрагироваться от параметров завода? Я чувствую, что с вышеуказанным заявлением переключиться, я сильно связаны с implemenations из IImplx, даже если у меня нет прямой ссылки.



14647
23
задан 21 января 2011 в 02:01 Источник Поделиться
Комментарии
2 ответа

Как о какой-то посредник доске, что клиентский код создает перед вызовом завода, и каждого конкретного осущ может опрашивать построить себя?

// client code:

Blackboard blackboard = new Blackboard();
blackboard.pushCollectionB(collectionB);
blackboard.pushCollectionC(collectionC);
blackboard.pushFoo(foo);

IImpl myInstance = Factory.GetInstance(b);

///////////////////////////

// in Factory.GetInstance():

return new Impl3(blackboard);

////////////////////////////

// in Impl3:

Impl3(Blackboard b) { process(b.getCollectionC()); }

Я спрятал оператора switch в коде клиента, но вы могли бы переместить, что в доске, а также.

Какие данные каждого конкретного должен осущ теперь скрыто от фабрики и код клиента. Однако если вам нужно больше данных в вашей доске для осущ(х+1) вам нужно обновлять каждое место в коде, который создает доски.

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

9
ответ дан 21 января 2011 в 02:01 Источник Поделиться

Мне кажется, что завод должен быть выбор ImplX на основе АРГ[1] вместо того, чтобы в ARG[0].

Это устранило бы необходимость для выключателя, АРГ[1] сейчас в ARG[0] в данном примере:

public IImpl GetInstance(params object[] args)
{
if (args.length == 0)
return new IImpl1();
else if (args[0] is IEnumerable<string>)
return new IImpl2(args[0]);
else
return new IImpl3(args[0]);
}

Затем вы могли бы назвать его как:

var impl1 = GetInstance();
var impl2 = GetInstance(new List<string>{"1","2"});
var impl3 = GetInstance("");

Редактировать:
Если вы не хотите, чтобы абонент должен знать внутренние работы о нем, то вы должны выставить перегрузок для деыпзьапсе так:

public IImpl GetInstance()
{
return new Impl1();
}
public IImpl GetInstance(IEnumberable<string> strings)
{
return new Impl2(strings);
}
public IImpl GetInstance(string string)
{
return new Impl3(string);
}

1
ответ дан 21 января 2011 в 07:01 Источник Поделиться