信息隐藏和函数式编程编码风格
Information hiding and functional programming coding style
我正在开发一个简单的 class,称为 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
class 的内部结构。 processable
方法完成的检查操作应该隐藏在 prepareOutput
方法中。
但是,让 processable
对 Simulator
可见,我可以应用更实用的方法,这非常方便。
哪种方法更好?我还缺少其他解决方案吗?
如果你需要隐藏 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());
}
由于您的 class Simulation
已经公开了可能会失败的操作 prepareOutput
,因此当您提供方法 processable
进行检测时,没有额外的公开提前,prepareOutput
操作是否会失败。实际上,提供这样的检查是一个很好的 API 设计,只要它不会太昂贵而无法提前计算。
您仍可以考虑在 Simulation
class.
期间提供批量处理操作
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
方法更简洁。
我正在开发一个简单的 class,称为 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
class 的内部结构。 processable
方法完成的检查操作应该隐藏在 prepareOutput
方法中。
但是,让 processable
对 Simulator
可见,我可以应用更实用的方法,这非常方便。
哪种方法更好?我还缺少其他解决方案吗?
如果你需要隐藏 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());
}
由于您的 class Simulation
已经公开了可能会失败的操作 prepareOutput
,因此当您提供方法 processable
进行检测时,没有额外的公开提前,prepareOutput
操作是否会失败。实际上,提供这样的检查是一个很好的 API 设计,只要它不会太昂贵而无法提前计算。
您仍可以考虑在 Simulation
class.
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
方法更简洁。