将策略模式,工厂模式和责任链模式结合起来以避免if / swich语句是否是个好主意?

时间:2017-01-12 19:52:40

标签: java design-patterns

将策略模式,工厂模式和责任链模式结合起来以避免if / swich语句是否是个好主意?

在正常情况下,策略上下文必须包含if或else语句来选择使用哪种策略。例如:

public class StrategyContext {
   @Autowired
   private Strategy defaultSt;
   @Autowired
   private Strategy otherSt;

   public void process(String message) {
       if(checkIfMessageIsFromStackOverflow(message))
            otherSt.doSomething();
       else if(checkIfMessageIsFromAnotherSite(message)) {
            defaultSt.doSomething();
       ......
       ......
   }

   //For example
   private boolean checkIfMessageIsFromStackOverflow(String message) {
       //over 15 lines of code where I parsing some message;
       return otherSt;
   }
   private boolean checkIfMessageIsFromAnotherSite(String message) {
       //over 20 lines of code..
       return defaultSt;
   }
}  

当然,在实践中,if with strategy选择逻辑比仅仅等于更复杂。
我认为这不是一个好的解决方案因为:

首先:在这种情况下,上下文变更策略本身,我认为在战略环境中应该从外部获得具体的策略。

其次:if / switch!每次创建新策略时,在StrategyContext中我们都要添加另一个if语句。我不是专家;但可能它违反了开放/封闭原则的规则。

我有一个想法是将if语句提取到责任链模式。每个链元素检查对象是否作为参数传递给链,必须处理它的策略并返回它或调用另一个链元素。

那么,你对它有什么看法?

2 个答案:

答案 0 :(得分:3)

责任链是链条中的一个元素可以承担责任并响应其收到的请求的链条。
一般来说,它意味着特定的规则来定义候选人是否有责任做出回应 除了你的情况,你应该有两个不同的类来区分战略关注和责任链关注,因为如果你想避免在他们内部承担太多的责任,那么两个关注点不应该混合在同一个类中。

当我看到你的代码时:

    if(strategy.equals("A"))
        defaultSt.doSomething();
    else if(strategy.equals("B")}
        ethoerSt.doSomething();

我认为不需要增加这种复杂性 您似乎没有需要一系列责任的明智规则。
相反,我认为一个简单的工厂基于一个地图,其中包含枚举或字符串作为关键字,作为一个策略实例的值,可以很好地完成这项工作。

答案 1 :(得分:2)

这里真实的事情:if if / else / switch事情往往不好OO

我的意思是:不要仅仅因为听到它们而遵循模式。而是查看模型并使其更有帮助。

示例:不要使用纯字符串来识别策略。给他们自己的班级甚至更好,一个枚举。然后你至少可以使用更健壮的枚举类型切换语句。

从那里开始:您的策略上下文可以使用Map例如:

public enum StrategyId { A, B; }

public StrategyContext {
   private final Map<StrategyId, Strategy> strategyById = ...

   public void process(StrategyId id) {
     strategyById.get(id).doSomething();
   }

并且,正如“Woot4Moo 4”所暗示的那样:请记住,策略不能是一个类 - 很可能是一个接口;让您获得更大的灵活性。