我正在开发一个名为Simulator
的简单类,它将Simulation
列表应用于某个输入。对于每个输入,模拟可以基于输入必须针对每个模拟实现的一些条件来产生或不产生输出。 Simulator
生成的结果是输出列表。
这是代码。
class Simulator {
final List<Simulation> simulations;
// Some initialization code...
List<Ouput> execute(Input input) {
return simulations
.stream()
.filter(s -> s.processable(input))
.map(s -> s.prepareOutput(input))
.collect(Collectors.toList());
}
}
正如您所看到的,首先我验证输入是否可由Simulation
处理,过滤不适合的模拟,然后将这些模拟应用于输入。
从面向对象的角度来看,我暴露了Simulation
类的内部。 processable
方法完成的检查操作应该隐藏在prepareOutput
方法中。
但是,如果processable
可见Simulator
,我可以应用更实用的方法,这非常方便。
哪种方法更好?我还缺少其他解决方案吗?
答案 0 :(得分:4)
由于您的班级Simulation
已经公开了可能失败的操作prepareOutput
,因此当您提供方法processable
提前检测时,没有额外的曝光,是否prepareOutput
1}}操作会失败。实际上,提供这样的检查是一个很好的API设计,只要提前计算它并不太昂贵。
您仍可以考虑在 Simulation
类中提供批量处理操作。
public class Simulation {
public Output prepareOutput(Input input) {
…
}
public static List<Output> prepareWhenPossible(List<Simulation> list, Input input) {
return simulations.stream()
.filter(s -> s.processable(input))
.map(s -> s.prepareOutput(input))
.collect(Collectors.toList());
}
}
让调用者明白它将跳过无法进行操作的元素,而不是实现“全有或全无”行为,这一点很重要。
如果实施起来很便宜,这仍然不排除公开processable
。这不是一个不可能的操作,因为总是可以只调用prepareOutput
并删除结果以确定操作是否可行。为此目的使用processable
方法更加清晰。
答案 1 :(得分:1)
如果你需要隐藏processable
,为什么不这样做有点不同:
Optional<Output> prepareOutput(Input input) {
boolean isProcessable = processable(input); // processable is private
if(isProcessable){
// prepare Output
return Optional.of(Output);
}
return Optional.empty();
}
然后是这样的事情:
List<Ouput> execute(Input input) {
return simulations
.stream()
.map(s -> s.prepareOutput(input))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}