我正在研究有很多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 :(得分:0)
从我的观点来看,第一个版本看起来更简单,更容易阅读,因此如果在第二个版本中没有性能获胜,我会继续使用它。提取一些通用方法会很好,但似乎不是那么直截了当,因为每个StateValidator
看起来都不同。