战略模式的这种变化是否有名称?

时间:2009-04-02 01:53:29

标签: design-patterns

我有一个标准的GOF策略模式:客户端代码包含对AbstractStrategy的引用,AbstractStrategy指向源自或实现AbstractStrategy的几个ConcreteStrategies中的任何一个。

一个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 Envelope / Letter(因为意图不完全相同)。

但它有名字吗?

3 个答案:

答案 0 :(得分:3)

似乎是 Anti-Pattern ; doStrategy具体的状态非常了解,每当添加新的具体策略时,您都必须更新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);

答案 1 :(得分:0)

它看起来像是策略和Factory method模式的组合。我怀疑它有自己的名字。 但为什么你真的需要switch语句?我认为Abstract Factory pattern会更好。

答案 2 :(得分: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(...)
  }
}

通过这种方式,策略的任何变化都只会改变应用程序的配置,而不是代码。