我必须通过一系列步骤处理请求。
例如:如果请求 1 到来,那么我必须应用步骤 1、步骤 2、步骤 3,最后应用步骤 4,这会将处理后的请求保存到数据库中。
我考虑实现模板设计模式,因为它解决了类似的问题。
当我开始实现设计模式时,我突然发现它很难实现,因为逻辑复杂。
让我解释一下要求:
请求 -> Controller -> run()
请求将包含 List<objects>
.
在run方法中,将触发一系列操作。
request.parallelStream()
.map(step1 -> executeStep1.apply(step1))
.map(step2 -> executeStep2.apply(step2, action))
.map(step3 -> executeStep3.apply(step3, rules))
.map(step4 -> executeStep4.apply(step4))
.collect(Collectors.toList());
Function<String, List<PersonDto>> executeStep1= person-> {
return metaData.getMetaDataPerson(person);
};
BiFunction<List<PersonDto>, String, TransTemplateDTO> executeStep2= (metaData, action) -> {
return temlate.createTemplate(metaData, action);
};
现在,正如我们所看到的,我正在传递 request
的第一个元素作为step1()的输入,然后对其进行处理,并进一步将输出作为输入传递给后续步骤。
问题 1:
到目前为止,没有任何问题。但突然需求发生了变化,现在我必须在步骤3中添加规则逻辑,即executeStep3.apply(step3)
。第3步有2个参数,第一个是第2步的输出,第二个是列表规则。
Step3 应应用所有规则并返回与规则相同的结果。
对于前。如果有 3 个规则,则步骤 3 应返回 3 个对象的列表。
假设步骤 3 收到了PersonDto
的列表有 10 个项目和 3 个项目的规则列表,则第 3 步应返回 10*3 = 30 条记录。
此外,每个人的规则都会根据命令而有所不同。问题 2:
在步骤 3 中,我需要请求对象,以便我可以使用值。 像这样的事情:
.map(step3 -> executeStep3.apply(step3, rules, request))
哪些设计模式可以提供帮助,以及如何提供帮助?
最佳答案
正如dung ta van已经提到的,首先想到的是责任链模式。我将重用该示例并更改其中的一些内容。
public class ChainOfResponsibility {
protected List<RequestProcessor> handlers = new ArrayList<>();
public void addHandler(RequestProcessor handler) {
this.handlers.add(handler);
}
@SuppressWarnings("unchecked")
public void handle(Request request) {
handlers
.stream()
.reduce(RequestProcessor::andThen)
.orElseThrow(() -> new RuntimeException("Functions can't be composed"))
.apply(request, null);
}
public interface RequestProcessor<T, R> extends BiFunction<Request, T, R> {
default <V> RequestProcessor<T, V> andThen(BiFunction<Request, ? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (Request r, T t) -> after.apply(r, apply(r, t));
}
}
public static class PersonExtractor implements RequestProcessor<Void, PersonDto> {
@Override
public PersonDto apply(Request request, Void aVoid) {
return new PersonDto("Nick");
}
}
public static class ValidatePersonHandler implements RequestProcessor<PersonDto, PersonDto> {
@Override
public PersonDto apply(Request request, PersonDto personDto) {
if (personDto.getName() == null) {
throw new IllegalArgumentException("name can't be null");
}
return personDto;
}
}
public static class SetPersonIdHandler implements RequestProcessor<PersonDto, List<?>> {
private final List<Rule> rules;
public SetPersonIdHandler(List<Rule> rules) {
this.rules = rules;
}
@Override
public List<?> apply(Request request, PersonDto personDto) {
personDto.setId(1);
rules.forEach(rule -> System.out.println("invoke rule " + rule.toString()));
return Arrays.asList(personDto, personDto, personDto);
}
}
public static class InsertPersonToDBHandler implements RequestProcessor<List<PersonDto>, Object> {
@Override
public List<?> apply(Request request, List<PersonDto> persons) {
persons.forEach(person -> System.out.println("insert person: " + person.getName() + " to db"));
return null;
}
}
public static void main(String[] args) {
ChainOfResponsibility chain = new ChainOfResponsibility();
chain.addHandler(new PersonExtractor());
chain.addHandler(new ValidatePersonHandler());
chain.addHandler(new SetPersonIdHandler(Arrays.asList(new Rule("1"), new Rule("2"))));
chain.addHandler(new InsertPersonToDBHandler());
chain.handle(new Request());
}
}
简而言之,我们引入了RequestProcessor
接口(interface),它确实是一个BiFunction
。我们将第一个参数绑定(bind)到 Request
上,第二个参数是上一个函数调用的结果。此外,每个处理程序也可以配置规则。
关于java - 使用 java 8 的设计模式建议/实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59451266/