2009-04-02 3 views
1

У меня стандартный шаблон стратегии GOF: код клиента содержит ссылку на AbstractStrategy, которая указывает на любую из нескольких ConcreteStrategies, полученных или реализующих AbstractStrategy.Имеет ли этот вариант шаблона стратегии имя?

Один ConcreteStrategy делегатов на любой из нескольких других ConcreteStrategies, в зависимости от его передаваемых параметров, например:

public class ConcreteStrategy0 { 
public void doStrategy(SomeType someData) { 
    switch(somefunc(someData) { 
    case 0: ConcreteStrategy1.singleton.doStrategy(someData); break; 
    case 1: ConcreteStrategy2.singleton.doStrategy(someData); break; 
    default: ConcreteStrategy3.singleton.doStrategy(someData); break; 
    } 
} 

Это не совсем Coplien Конверт/Письмо (как намерение не совсем то же самое) ,

Но имеет ли это название?

ответ

0

Похож на комбинацию Стратегии и Factory method. Я сомневаюсь, что у него есть собственное имя. Но почему вам действительно нужна инструкция switch? Я думаю, что здесь будет приятнее Abstract Factory pattern.

+0

Коммутатор должен показать, что делает код, а не настаивать на конкретной реализации. На практике, однако, я не знаю, что в рамках реализации ConcreteStrategy я хочу делегировать еще одну иерархию стратегий классов. – tpdi

+0

О, и это не Factory, я не думаю: Factory - это Object Creation pagttern, и здесь ничего не создается, тем более создается тип подкласса. Мы просто выбираем три альтернативы. – tpdi

+0

Хорошо, что оператор switch в вашем примере довольно заметен, поэтому его нельзя просто игнорировать. И это часть дизайна. Задача здесь состоит в том, как избавиться от нее (http://c2.com/cgi/wiki?SwitchStatementsSmell), используя другой более элегантный способ. –

3

Похоже, что Anti-Pattern; doStrategy слишком много знает о бетон stategy и всякий раз, когда добавляется новая конкретная стратегия, вы должны обновить doStrategy.

Вышеуказанный код нарушает Open/Closed Principle, и мне интересно, можно ли его назвать или иметь имя выше code.


После мыслей: При вызове ConcreteStrategy0.doStrategy, вы в основном называют это как

new ConcreteStrategy0().doStrategy(someData); 

Хотя это могло быть лучше переработан в

// Inject strategy: Delegate object creation to a factory 
new ConcreteStrategy0().doStrategy(StrategyFactory.Create(), someData); 

// And update "doStrategy" to, 
public void doStrategy(IStrategy strategy, SomeType someData) 
{ 
    strategy.singleton.doStrategy(someData); 
} 

Или делегировать ответ на стратегию в целом,

// OR Let the strategy do stuff instead 
StrategyFactory.Create().doStrategy(someData); 
0

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

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

<bean id="client" class="..."> 
    <property name="strategy" ref="dispatcherStartegy"/> 
</bean> 
<bean id="dispatcherStartegy" class="..."> 
    <property name="strategies"> 
    <map> 
     <entry key="0" ref="concreteStrategy1"/> 
     <entry key="1" ref="concreteStrategy2"/> 
    </map> 
    </property> 
    <property name="fallbackStrategy" ref="concreteStrategy3"/> 
</bean> 
<bean id="concreteStrategy1" ... /> 
<bean id="concreteStrategy2" ... /> 
<bean id="concreteStrategy3" ... /> 

И классы будет выглядеть следующим образом:

class Client { 
    Strategy strategy; 
    public void setStrategey(Strategy strategy {... } 
    public void doSomething(...) { 
    ... 
    strategy.doStrategy(...); 
    ... 
    } 
} 

class DispatcherStrategy implements Strategy { 
    Map<Integer,Strategy> strategies; 
    Strategy fallbackStrategy; 
    ... getters, setters ... 
    public void doStrategy(...) { 
    Strategy s = strategies.get(keyFromArguments); 
    if (s==null) { 
     s = fallbackStrategy 
    } 
    s.doStrategy(...) 
    } 
} 

И в этом случае любое изменение в стратегии будет просто изменить конфигурацию приложения, а не код.

Смежные вопросы