Oop 信息隐藏与函数式编程编码风格
我正在开发一个简单的类,名为Oop 信息隐藏与函数式编程编码风格,oop,functional-programming,java-8,java-stream,information-hiding,Oop,Functional Programming,Java 8,Java Stream,Information Hiding,我正在开发一个简单的类,名为Simulator,它将Simulation列表应用于特定的输入。对于每个输入,模拟可以产生输出,也可以不产生输出,这取决于输入必须满足的与每个模拟相关的一些条件。模拟器产生的结果是一个输出列表 这是代码 class Simulator { final List<Simulation> simulations; // Some initialization code... List<Ouput> execute(In
Simulator
,它将Simulation
列表应用于特定的输入。对于每个输入,模拟可以产生输出,也可以不产生输出,这取决于输入必须满足的与每个模拟相关的一些条件。模拟器产生的结果是一个输出列表
这是代码
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());
}
}
类模拟器{
最终清单模拟;
//一些初始化代码。。。
列表执行(输入){
返回模拟
.stream()
.filter(s->s.可处理(输入))
.map(s->s.prepareOutput(输入))
.collect(Collectors.toList());
}
}
如您所见,首先,我验证输入是否可由模拟处理,过滤不可处理的模拟,然后将这些模拟应用于输入
从面向对象的角度来看,我公开了Simulation
类的内部结构。processable
方法执行的检查操作应隐藏在prepareOutput
方法中
但是,由于模拟器
可以看到可处理的
,我可以应用一种功能更强大的方法,这非常方便
哪种方法更好?我还缺少其他解决方案吗?如果需要隐藏可处理的
,为什么不做一些不同的事情:
Optional<Output> prepareOutput(Input input) {
boolean isProcessable = processable(input); // processable is private
if(isProcessable){
// prepare Output
return Optional.of(Output);
}
return Optional.empty();
}
可选准备输出(输入){
布尔值isProcessible=可处理(输入);//可处理是私有的
if(可处理){
//准备输出
返回可选。of(输出);
}
返回可选的.empty();
}
然后像这样:
List<Ouput> execute(Input input) {
return simulations
.stream()
.map(s -> s.prepareOutput(input))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}
列表执行(输入){
返回模拟
.stream()
.map(s->s.prepareOutput(输入))
.filter(可选::isPresent)
.map(可选::get)
.collect(Collectors.toList());
}
由于您的类模拟
已公开操作prepareOutput
,该操作可能会失败,因此当您提供方法可处理
以提前检测prepareOutput
操作是否会失败时,没有额外的公开。事实上,提供这样的检查是一种很好的API设计,只要事先计算不会太昂贵
您仍然可以考虑在<代码>模拟< /代码>类中提供批量处理操作。
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());
}
}
公共类模拟{
公共输出准备输出(输入){
…
}
公共静态列表准备(列表列表,输入){
return.stream()
.filter(s->s.可处理(输入))
.map(s->s.prepareOutput(输入))
.collect(Collectors.toList());
}
}
重要的是要让调用者清楚地知道,它将跳过不可能执行操作的元素,而不是实现“要么全有,要么全无”的行为
这仍然不排除公开可处理的
,如果实现起来很便宜的话。这并不是说这是一个不可能的操作,因为总是可以调用prepareOutput
并删除结果以确定该操作是否可能。有一个可处理的
方法来实现这个目的要干净得多。如果你认为你是在暴露内部,那么为什么要这样做呢?需要思考的其他一些问题:如果我使用someSimulation.prepareOutput(null)
调用您的任何模拟,会发生什么?这是可以处理的吗?或者,如果我使用给定模拟无法处理的输入参数调用prepareOutput
,会发生什么?我是否需要从外部了解或检查其加工性能?它是返回null
还是抛出异常?是可选的吗
是一个选项吗?但这只是在技术上隐藏了可处理的
,而不是在语义上,因为每个人都可以去写一个方法布尔可处理的(模拟s,输入i){返回s.prepareOutput(i).isPresent();}
,所以隐藏可处理的
实现了,这可能会降低测试的效率。@Holger谢谢你,说得好。我以为这只是为了隐藏唯一的方法。对于批量处理,您的答案还有一个。我认为您遇到了问题:如果processable
方法可用于其他类型,那么方法prepareOutput
在内部调用它是很重要的。在此透视图下,prepareOutput
无论如何都应该返回一个可选的。