我創建了下面提到的基類和派生類
public abstract class ContextBase {
private String customerID;
private String marketplaceID;
}
public class ReturnContext extends ContextBase {
private String returnID;
}
然后我創建了一個介面,它有一個名為 perform 的方法和一些實作這個介面的類
public interface ValidatorInterface<T extends ContextBase> {
CompletableFuture<List<String>> perform(T context);
}
public class AlphaValidator implements ValidatorInterface<ContextBase> {
@Override
public CompletableFuture<List<String>> perform(ContextBase contextBase) {
....
}
}
public class BetaValidator implements ValidatorInterface<ReturnContext> {
@Override
public CompletableFuture<List<String>> perform(ReturnContext context) {
....
}
}
我想運行一個并行實作 ValidatorInterface 的類串列,所以我創建了一個 ValidatorRunner 類
public class ValidatorRunner<T extends ContextBase> {
public List<String> runValidators(final T context,
final List<ValidatorInterface<T>> validatorsList) {
final Map<String, CompletableFuture<List<String>>> futureAggregatedProblems = new LinkedHashMap<>(validatorsList.size());
List<String> problems = new ArrayList<>();
validatorsList.forEach(validator -> runValidator(
validator, futureAggregatedProblems, context));
futureAggregatedProblems.forEach((validatorName, futureProblems) -> {
try {
problems.addAll(futureProblems.get(FUTURE_TIMEOUT_MS, TimeUnit.MILLISECONDS));
} catch (InterruptedException | ExecutionException | CompletionException | TimeoutException ex) {
// TODO Do not ignore InterruptedException
throw new InternalServiceException("Error executing validators : " ex.getMessage(), ex);
}
});
return problems;
}
private void runValidator(final ValidatorInterface<T> validator,
final Map<String, CompletableFuture<List<String>>> futureAggregatedProblems,
final T context) {
futureAggregatedProblems.put(validator.getClass().getCanonicalName(), validator.perform(context));
}
當我這樣做時,這個實作似乎確實有效
ValidatorRunner<ReturnContext> validatorRunner = new ValidatorRunner<ReturnContext>();
ReturnContext context = new ReturnContext();
BetaValidator beta = new BetaValidator();
List<ValidatorInterface<ReturnContext>> validatorList = new ArrayList<>();
validatorList.add(beta);
List<String> problems = validatorRunner.runValidators(context, validatorList);
問題是 AlphaValidator 是在基型別 (ContextBase) 上實作的,而 BetaValidator 是在派生型別 (ReturnContext) 上實作的。我想在將 ReturnContext 的實體作為背景關系傳遞時并行運行 AlphaValidator 和 BetaValidator。它是如何實作的?
編輯 1
我創建 ValidatorInterface 作為T 擴展 ContextBase的原因是我希望每個驗證器使用 ContextBase 或 ContextBase 的派生類。
我在基本型別 ContextBase 上創建了 AlphaValidator,因為我希望使用 ContextBase 的任何派生類來創建和執行 AlphaValidator。在 ReturnContext 上創建 BetaValidator 時,因為我希望僅使用 ReturnContext 創建和執行 BetaValidator。假設我創建了一個名為 ReplacementContext 的新派生類,它擴展了 ContextBase,并且還在派生型別 ReplacementContext 上創建了一個名為 GammaValidator 的新驗證器。我希望能夠使用 ReplacementContext 運行 AlphaValidator 和 GammaValidator。AlphaValidator 和 BetaValidator 應該在 ReturnContext 上運行。但我不想并行運行 BetaValidator 和 GammaValidator,因為它們服務于不同的目的和不同的背景關系(這就是為什么它們分別在不同的背景關系、ReturnContext 和 ReplacementContext 上創建)。
uj5u.com熱心網友回復:
上面代碼有問題
當為多個驗證器提供單個具體背景關系時,每個驗證器必須支持給定的背景關系類。這是一個設計問題。
我的解決方案
另一種解決方案是為runValidate方法提供多個背景關系,其中每個背景關系都可以放置在正確的驗證器旁邊。
鑒于我的示例,ContextProcessor.of()將注意編譯器只允許對驗證器和背景關系進行正確分配。
我建議將您更改ValidatorRunner為與此代碼類似的版本:
public class ValidatorRunner {
static class ContextProcessor<T extends ContextBase> {
private final List<ValidatorInterface<T>> validators;
private final T context;
private ContextProcessor(List<ValidatorInterface<T>> validators, T context) {
this.validators = validators;
this.context = context;
}
public static <V extends ValidatorInterface<C>, C extends ContextBase> ContextProcessor<C> of(List<V> validators, C context) {
//noinspection unchecked
return new ContextProcessor<>((List<ValidatorInterface<C>>) validators, context);
}
public List<ValidatorInterface<T>> getValidators() {
return validators;
}
public T getContext() {
return context;
}
}
public List<String> runValidators(final List<ContextProcessor<? extends ContextBase>> processors) {
var validators = processors.stream().map(p -> p.validators.size()).reduce(Integer::sum).orElse(0);
var latch = new CountDownLatch(validators);
var problemStack = new ArrayList<String>();
//noinspection unchecked
processors.forEach(p -> p.getValidators().forEach(validator ->
runValidator((ValidatorInterface<ContextBase>) validator, p.getContext())
.orTimeout(10_000L, TimeUnit.MILLISECONDS)
.thenAccept(problems -> {
problemStack.addAll(problems);
latch.countDown();
})
));
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return problemStack;
}
private CompletableFuture<List<String>> runValidator(final ValidatorInterface<ContextBase> validator, final ContextBase context) {
return validator.perform(context);
}
public static void main(String[] args) {
var problems = new ValidatorRunner().runValidators(
List.of(
ContextProcessor.of(List.of(new AlphaValidator(), new AlphaValidator()), new ReplacementContext()),
ContextProcessor.of(List.of(new AlphaValidator()), new ContextBase() {}),
ContextProcessor.of(List.of(new BetaValidator(), new BetaValidator()), new ReturnContext())
)
);
System.out.println(problems);
}
}
運行提供的main方法時,預期會出現以下結果:
[error within context ReplacementContext, error within context ReplacementContext, error within context , error within context ReturnContext, error within context ReturnContext]
每個驗證器都回傳了Future字串"error within context" context.getClass().getSimpleName()
也許這將幫助您找到解決問題的方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/487434.html
