2017-07-28 10 views
0

我正在處理遺留代碼,其中有很多if/else。我可以使用條件分解和/或守衛語句等來清除它。可以使用的另一種方法是從分支中創建函數,並將這些函數作爲鏈並以第一個響應退出。我想知道如果使用功能鏈是一種矯枉過正?任何意見?如果其他分支和清理代碼使用功能鏈減少,這是否有意義

我的鏈看起來像下面。這是一個簡單的例子。

public class RequestStateHandler { 
    private final List<Function<RequestStateInfo, Optional<Response>>> handlers = new ArrayList<>(); 

    public RequestStateHandler() { 
     handlers.add(requestStateInfo -> xStateValidator(requestStateInfo)); 
     handlers.add(requestStateInfo -> yStateValidator(requestStateInfo)); 
     handlers.add(requestStateInfo -> zStateValidator(requestStateInfo)); 
    } 

    public Response getResponse(RequestStateInfo requestStateInfo) { 
     try { 
      for (final Function<RequestStateInfo, Optional<Response>> handler : handlers) { 
       final Optional<Response> response = handler.apply(requestStateInfo); 

       if (response.isPresent()) { 
        return response.get(); 
       } 
      } 
     } catch (Exception e) { 
      LOGGER.error("Some log", e); 
     } 

     return getDefaultResponse(requestStateInfo); 
    } 

    private Optional<Response> xStateValidator(RequestStateInfo requestStateInfo) { 
     final A a = requestStateInfo.getA(); 
     if (a.isABC()) { 
      return Optional.of(requestStateInfo.getX()); 
     } 

     return Optional.empty(); 
    } 

    private Optional<Response> yStateValidator(RequestStateInfo requestStateInfo) { 
     if (requestStateInfo.isXYZ()) { 
      final Response response = requestStateInfo.getX(); 
      final A a = response.getA(); 
      if (a.isSomeOtherTest()) { 
       return Optional.of(response); 
      } 
     } 

     return Optional.empty(); 
    } 

    private Optional<Response> zStateValidator(RequestStateInfo requestStateInfo) { 
     final Response response = requestStateInfo.getX(); 
     final A a = response.getA(); 
     if (a.isSomeAnotherTest()) { 
      return Optional.of(response); 
     } 

     return Optional.of(getDefaultResponse(requestStateInfo)); 
    } 

    private Response getDefaultResponse(RequestStateInfo requestStateInfo) { 
     return new Response(A.create(requestStateInfo.getY()), null, null, null); 
    } 
} 

我想創建一個可重用的執行程序,以便我們在這裏只有業務邏輯。對我來說,它看起來更清潔,但它顯然增加了依賴性來按順序執行這些功能。我會說,就像責任鏈一樣。你怎麼看?

一個通用的執行者可能是這樣的:

import org.apache.commons.lang3.Validate; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.Optional; 
import java.util.function.Consumer; 
import java.util.function.Function; 
import java.util.function.Supplier; 

public class ChainedExecutor<T, R> { 
    private final static Logger LOGGER = LoggerFactory.getLogger(ChainedExecutor.class); 
    public final List<Function<T,Optional<R>>> handlers; 
    private R defaultResponse; 

    private ChainedExecutor() { 
     this.handlers = new ArrayList<>(); 
    } 

    public R execute(T request) { 
     return execute(request, Optional.empty(), Optional.empty()); 
    } 

    public R execute(T request, Function<T, R> defaultSupplier) { 
     return execute(request, Optional.of(defaultSupplier), Optional.empty()); 
    } 

    public R execute(T request, Consumer<Exception> exceptionHandler) { 
     return execute(request, Optional.empty() ,Optional.of(exceptionHandler)); 
    } 

    public R execute(T request, Function<T, R> defaultHandler, Consumer<Exception> exceptionHandler) { 
     return execute(request, Optional.of(defaultHandler), Optional.of(exceptionHandler)); 
    } 

    public R execute(T request, Supplier<R> defaultSupplier) { 
     final Function<T, R> defaultHandler = (input) -> defaultSupplier.get(); 
     return execute(request, Optional.of(defaultHandler), Optional.empty()); 
    } 

    private R execute(T request, Optional<Function<T, R>> defaultHandler, Optional<Consumer<Exception>> exceptionHandler) { 
     Optional<R> response; 
     try { 
      for (final Function<T,Optional<R>> handler: handlers) { 
       response = handler.apply(request); 

       if (response.isPresent()) { 
        return response.get(); 
       } 
      } 
     } 
     catch (Exception exception) { 
      handleOrLog(exceptionHandler, exception); 
     } 

     return getDefaultResponse(defaultHandler, request); 
    } 

    private void handleOrLog(Optional<Consumer<Exception>> exceptionHandler, Exception exception) { 
     if (exceptionHandler.isPresent()) { 
      exceptionHandler.get().accept(exception); 
      return; 
     } 
     LOGGER.error("Unhandled exception occurred while executing handler chain. This most probably is a developer error."); 
    } 

    private R getDefaultResponse(Optional<Function<T, R>> defaultHandler, T request) { 
     if (defaultHandler.isPresent()) { 
      return defaultHandler.get().apply(request); 
     } 
     return getDefaultResponse(); 
    } 

    public R getDefaultResponse() { 
     return defaultResponse; 
    } 

    public static class Builder<T, R> { 
     private final ChainedExecutor<T, R> chainedExecutor = new ChainedExecutor<>(); 

     public Builder(List<Function<T,Optional<R>>> handlers) { 
      Validate.notNull(handlers); 
      for (final Function<T, Optional<R>> handler: handlers) { 
       Validate.notNull(handler); 
       handlers.add(handler); 
      } 
     } 

     public Builder() {} 

     public ChainedExecutor.Builder<T, R> withHandler(Function<T, Optional<R>> handler) { 
      Validate.notNull(handler); 
      chainedExecutor.handlers.add(handler); 
      return this; 
     } 

     public ChainedExecutor.Builder<T, R> withDefaultResponse(R defaultResponse) { 
      Validate.notNull(defaultResponse); 
      chainedExecutor.defaultResponse = defaultResponse; 
      return this; 
     } 

     public ChainedExecutor<T, R> build() { 
      Validate.isTrue(!chainedExecutor.handlers.isEmpty()); 
      return chainedExecutor; 
     } 
    } 
} 

編輯

我最終沒有這樣做。這只是一個想法而已。我覺得這會讓我的同事更加神祕。雖然,我真的很喜歡刪除if/else。我去了OOPS的方式(多態)。

回答

0

從我的角度來看,第一個版本看起來更簡單,更容易閱讀,因此如果在第二個版本中沒有獲勝的話,我會這樣做。一些通用方法的提取會很好,但它似乎並不那麼直截了當,因爲每個StateValidator看起來都不一樣。

相關問題