我有一个标准的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(因为意图不完全相同)。
但它有名字吗?
答案 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(...)
}
}
通过这种方式,策略的任何变化都只会改变应用程序的配置,而不是代码。