英文:
Java 8: Applying a list of methods on one object
问题
我在代码中有一个特定的部分,我想做的就是下面这样,但我不知道如何编写,以避免代码重复。是否有一种方法,我可以声明一个方法列表,然后将其应用于`productFeatureValidationDto`。我目前的方法很新手。
public ValidateProductFeatureResponse validateProductFeatureAgainstAllCriteria(ProductFeatureValidationDto productFeatureValidationDto) throws
ApplicationException, ParseException {
ValidateProductFeatureResponse response;
List<Function<ProductFeatureValidationDto, ValidateProductFeatureResponse>> validationMethods = new ArrayList<>();
validationMethods.add(this::validateProductFeatureA);
validationMethods.add(this::validateProductFeatureB);
validationMethods.add(this::validateProductFeatureC);
validationMethods.add(this::validateProductFeatureD);
validationMethods.add(this::validateProductFeatureE);
validationMethods.add(this::validateProductFeatureF);
for (Function<ProductFeatureValidationDto, ValidateProductFeatureResponse> method : validationMethods) {
response = method.apply(productFeatureValidationDto);
if (response.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name())) {
return response;
}
}
return getResponseOnValidationSuccess(productFeatureValidationDto);
}
英文:
I have a particular part in code where all I want to do is the below, but I am at a loss to write in a way that doesn't involve code repetition. Is there a way that I can declare a list of methods, which can be then applied to productFeatureValidationDto
. My current approach is noob-ish.
public ValidateProductFeatureResponse validateProductFeatureAgainstAllCriteria(ProductFeatureValidationDto productFeatureValidationDto) throws
ApplicationException, ParseException {
ValidateProductFeatureResponse response;
response = this.validateProductFeatureA(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name())){
return response;
}
response = this.validateProductFeatureB(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name())){
return response;
}
response = this.validateProductFeatureA(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(MPResponseStatus.FAILURE.name())){
return response;
}
response = this.validateProductFeatureC(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(MPResponseStatus.FAILURE.name())){
return response;
}
response = this.validateProductFeatureD(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name())){
return response;
}
response = this.validateProductFeatureE(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name())){
return response;
}
response = this.validateProductFeatureF(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name())){
return response;
}
return getResponseOnValidationSuccess(productFeatureValidationDto);
}
Thanks in advance.
答案1
得分: 0
如果您能够使用Spring框架,
首先,您可以定义一个类似这样的接口。
```java
public interface ValidateProduct{
ValidateProductFeatureResponse validate(ProductFeatureValidationDto dto);
}
您的具体验证类实现了这个接口并注册到Spring上下文中。
public ValidateProductFeatureResponse validateProductFeatureAgainstAllCriteria(ProductFeatureValidationDto productFeatureValidationDto) throws
ApplicationException, ParseException {
ValidateProductFeatureResponse response;
Map<String, ValidateProduct> beansOfType = applicationContext.getBeansOfType(ValidateProduct.class);
for (ValidateProduct value : beansOfType.values()) {
response = value.validate(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name())){
return response;
}
}
return getResponseOnValidationSuccess(productFeatureValidationDto);
}
<details>
<summary>英文:</summary>
if you can use spring framework.
at first you can define an interface like this.
```java
public interface ValidateProduct{
ValidateProductFeatureResponse validate(ProductFeatureValidationDto dto);
}
Your specific verification class implements this interface and register to srpingcontext
public ValidateProductFeatureResponse validateProductFeatureAgainstAllCriteria(ProductFeatureValidationDto productFeatureValidationDto) throws
ApplicationException, ParseException {
ValidateProductFeatureResponse response;
Map<String, ValidateProduct> beansOfType = applicationContext.getBeansOfType(ValidateProduct.class);
for (ValidateProduct value : beansOfType.values()) {
response = value.validate(productFeatureValidationDto);
if(response.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name())){
return response;
}
}
return getResponseOnValidationSuccess(productFeatureValidationDto);
}
答案2
得分: 0
我建议采取以下方法(示意图):
/**
* 验证函数列表
*/
private final static List<Function<ProductFeatureValidationDto, ProductFeatureValidationDto>> VALIDATIONS = new LinkedList<>();
/**
* 填充验证列表
*/
static {
VALIDATIONS.add((source) -> {
// 针对特性 A 的测试
return source;
});
VALIDATIONS.add((source) -> {
// 针对特性 B 的测试
return source;
});
VALIDATIONS.add((source) -> {
// 针对特性 C 的测试
return source;
});
}
/**
* 失败判定的断言
*/
private final Predicate<ProductFeatureValidationDto> IS_FAILURE = (dto) ->
dto.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name());
/**
* 验证方法
*/
public ValidateProductFeatureResponse validateProductFeatureAgainstAllCriteria(
ProductFeatureValidationDto dto
) throws ApplicationException, ParseException {
// 遍历验证函数并在 dto 实例上调用它们
// 根据失败的验证筛选流
// 在第一个匹配时停止
Optional<ProductFeatureValidationDto> dtoOptional = VALIDATIONS.stream()
.map(action -> action.apply(dto))
.filter(IS_FAILURE)
.findFirst();
// 根据结果应用失败/成功映射
return dtoOptional.isPresent()
? getResponseOnValidationFailure(dto)
: getResponseOnValidationSuccess(dto);
}
英文:
I would suggest following approach (schematic):
/**
* List of validation functions
*/
private final static List<Function<ProductFeatureValidationDto, ProductFeatureValidationDto>> VALIDATIONS = new LinkedList<>();
/**
* Fill validations list
*/
static {
VALIDATIONS.add((source) -> {
// test for feature A
return source;
});
VALIDATIONS.add((source) -> {
// test for feature B
return source;
});
VALIDATIONS.add((source) -> {
// test for feature C
return source;
});
}
/**
* Predicate for failure determination
*/
private final Predicate<ProductFeatureValidationDto> IS_FAILURE = (dto) ->
dto.getStatus().equalsIgnoreCase(ResponseStatus.FAILURE.name());
/**
* Validation method
*/
public ValidateProductFeatureResponse validateProductFeatureAgainstAllCriteria(
ProductFeatureValidationDto dto
) throws ApplicationException, ParseException {
// iterate over validation functions and invoke them on dto instance
// filter stream by failed validations
// stop on first match
Optional<ProductFeatureValidationDto> dtoOptional = VALIDATIONS.stream()
.map(action -> action.apply(dto))
.filter(IS_FAILURE)
.findFirst();
// apply fuilure / success maping depending on result
return dtoOptional.isPresent()
? getResponseOnValidationFailure(dto)
: getResponseOnValidationSuccess(dto);
}
答案3
得分: 0
以下是翻译好的内容:
我最终是根据 @Eiden 和 @Alexandra Dudkina 给出的答案来组合我的解决方案的。非常感谢他们。以下是我整个解决方案的要点。
所以,我有两个接口:
IProductFeature
:这是一个功能接口,只有一个方法validate
。每个约束都需要实现这个接口。IProductValidationService
:这是一个约定,指定了需要实现的核心方法。方法validateProductFeatureAgainstAllCriteria
是约定的一部分。
有一个配置文件,将所有的功能导入并按照不同类型的产品进行了组织成列表。这个列表已经被保存在一个以产品类型为键的映射中。因此,这就像一个工厂,根据给定的产品类型提供了一个约束列表。
实现 IProductValidationService
的具体类从配置中获取列表,然后将列表中的所有约束应用于给定的数据传输对象(dto)。通过这种方式,我将所有关注点分离到了不同的部分。
这种方法的实际优势包括:
- 您可以为单个功能编写广泛的测试用例和文档。
- 如果将来在
ProductFeatureB
(例如)中有政策变更,我只需要创建一个新的具体类,称其为ProductFeatureBV2
,并仅更改配置文件。政策变更可以作为类注释的一部分进行记录。这样,在不改变核心验证方法的情况下,我可以废弃ProductFeatureB
。这使得代码变得非常灵活。
非常感谢社区帮助我正确地完成这个任务。如果还有进一步的改进建议,请提出。
英文:
I ended up composing my solution from the answers given by @Eiden and @Alexandra Dudkina. A big shoutout to them. Below is the crux of my whole solution.
So, I have two interfaces
IProductFeature
: This is a functional interface which has only one methodvalidate
. Every constraint needs to implement this.IProductValidationService
: This is a contract specifying the core methods needed to be implemented. The methodvalidateProductFeatureAgainstAllCriteria
is part of the contract.
There is a config file where all the features have been imported and organised into lists as required for different kinds of products. This list has been kept in a map with the product type as key. So this is acting like a factory which is giving a list of constraint based on a given product type.
The concrete class implementing IProductValidationService
gets the list from the config and then applies all the constraints in the list to the given dto.
This way, I have separated all the concerns into separate portions.
The practical advantages to this approach are:
- You can write extensive test cases and documentation for individual features.
- If in the future, there is a policy change in
ProductFeatureB
(for e.g.),all I have to do is create a new concrete class, call it ProductFeatureBV2 and change only config file. The policy changes can be documented as part of the class javadoc. This way without changing core validation method, I can deprecateProductFeatureB
. This makes the code extremely flexible.
Thanks a lot to the community for helping me getting this right. If there are further improvements to be made here, please suggest them.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论