一长串if / else / execute代码分支的最佳设计模式/方法

时间:2015-03-07 16:05:40

标签: java oop design-patterns refactoring

我有一个“遗留”代码,我想重构。
代码基本上是对服务器的远程调用并获得回复。然后根据回复执行相应的 代码骨架的例子:

public Object processResponse(String responseType, Object response) {
    if(responseType.equals(CLIENT_REGISTERED)) {  
       //code  
       //code ...
    }  
    else if (responseType.equals(CLIENT_ABORTED)) {
       //code  
       //code....
    }    
    else if (responseType.equals(DATA_SPLIT)) {
      //code
      //code... 
   }  
   etc  

问题在于,有很多if / else分支,并且每个分支内部的代码都不是微不足道的 因此很难维持 我想知道这个最好的模式是什么? 我有一个想法是创建一个方法名称与responseType相同的单个对象,然后在processResponse内部使用反射调用与responseType同名的方法。
这会清理processResponse,但它会将代码移动到具有许多/多种方法的单个对象,我认为反射会导致性能问题。
是否有一个很好的设计方法/模式来清理它?

3 个答案:

答案 0 :(得分:6)

两种方法:

  1. 策略模式http://www.dofactory.com/javascript/strategy-design-pattern
  2. 创建字典,其中key是元数据(在您的情况下元数据是responseType),value是一个函数。
  3. 例如:

    将它放在构造函数

    responses = new HashMap<string, SomeAbstraction>(); responses.Put(CLIENT_REGISTERED, new ImplementationForRegisteredClient()); responses.Put(CLIENT_ABORTED, new ImplementationForAbortedClient());

    其中ImplementationForRegisteredClientImplementationForAbortedClient实施SomeAbstraction

    并通过此字典调用 responses.get(responseType).MethodOfYourAbstraction(SomeParams);

    如果您想遵循DI的原则,可以在您的客户端类中注入此Dictionary。

答案 1 :(得分:2)

我的第一个切割是用switch / case替换if / else if结构:

public Object processResponse(String responseType, Object response) {
    switch(responseType) {
        case CLIENT_REGISTERED: {  
       //code ...
    }  
    case CLIENT_ABORTED: {
       //code....
    }    
    case DATA_SPLIT: {
      //code... 
   }  

从那里我可能会提取每个块作为一种方法,并从那里应用策略模式。在任何感觉正确的地方停下来。

答案 2 :(得分:0)

您描述的案例似乎完全适合策略模式的应用。特别是,您有许多算法变体,即根据远程服务器调用的响应执行的代码。

实现Stategy模式意味着您必须定义一个类层次结构,如下所示:

public interface ResponseProcessor {
   public void execute(Context ctx);
}
class ClientRegistered implements ResponseProcessor {
   public void execute(Context ctx) {
      // Actions corresponding to a client that is registered
      // ...
   }
}
class ClientAborted implements ResponseProcessor {
   public void execute(Context ctx) {
      // Actions corresponding to a client aborted
      // ...
   }
}
// and so on...

Context类型应包含执行每个“策略”所需的所有信息。请注意,如果不同的策略共享一些算法片段,您也可以使用其中的 Templeate方法模式

您需要 factory 才能在运行时创建特定策略。工厂将根据收到的回复制定战略。可能的实现应该是@Sattar Imamov建议的实现。工厂将包含if .. else代码。

如果策略类的构建时间不重,并且在构建时不需要任何外部信息,您也可以将每个策略映射到枚举值。

public enum ResponseType {
   CLIENT_REGISTERED(new ClientRegistered()),
   CLIENT_ABORTED(new ClientAborted()),
   DATA_SPLIT(new DataSplit());

   // Processor associated to a response
   private ResponseProcessor processor;

   private ResponseType(ResponseProcessor processor) {
      this.processor = processor;
   }
   public ResponseProcessor getProcessor() {
      return this.processor;
   }
}