具有闭包的语言(例如Ruby)使得优雅的构造能够转换列表.假设我们有一个班级
class QueryTerm {
String value;
public String getValue() {...}
}
Run Code Online (Sandbox Code Playgroud)
以及List<QueryTerm> terms我们想要转换为其值列表的术语列表List<String> values.
在Ruby中我们可以编写如下内容:
values1 = terms.collect do |term|
term.getValue()
end
Run Code Online (Sandbox Code Playgroud)
Java强制我们构造结果列表并自己遍历术语集合(至少在引入foreach之后没有涉及迭代器或索引位置):
Collection<String> values2 = new HashSet<String>();
for (QueryTerm term : terms) {
values2.add(term.getValue());
}
Run Code Online (Sandbox Code Playgroud)
Apache Commons和Google Collections2尝试使用匿名类来模拟Java中的闭包:
Collection<String> values3 = Collections2.transform(terms, new Function<QueryTerm, String>() {
@Override
public String apply(QueryTerm term) {
return term.getValue();
}
});
Run Code Online (Sandbox Code Playgroud)
奇怪的是,这个版本有更多的代码行和比原始版本更多的字符!我认为由于这个原因很难理解.因此,当我在Apache Commons中看到它时,我就驳回了这个想法.然而,最近我在谷歌收藏中看到它,我开始怀疑我是否遗漏了一些东西.
因此我的问题是:您对上述结构有何看法?您认为该Collections2.transform()版本比默认版本更易读/可理解吗?我完全错过了什么吗?
最好的问候,约翰内斯
这里使用的闭包与Command模式几乎相同.我猜这里命令有用的任何原因都适用于此.A当然Command也可能比闭包稍微完全成熟,因为后者仅在功能级别上.但一个关键的观察是,这通常都是你需要的.
有一些优势对我来说很明显:
控制反转:假设您想要在几个不同的线程上分解您的操作.如果您编写了自己的循环,那么您现在已经陷入困境:您必须自己将其分解为几个不同的循环.编写代码通常很难看,而且需要你创建几个可以传递给其他线程的Runnables.所以你真的只是再次使用封闭装置.
其中一个JDK7提案显然无法完成这一切,只需提交您的数据并定义要在其上执行的过滤器,您就可以采用它的快乐方式.您实际上可以下载此代码(包extra166y).您可以在javadoc中看到的用于此包的所有操作都可以删除并替换为闭包.所以这是一个很好的例子,为什么某种方法由于缺乏真正的闭包而失败,并且"模拟"闭包不再完全削减它.
实际上,通过传递一个简单的函数可以轻松解决大量问题,这个函数可以执行您希望它对数据执行的操作,并让框架填充其余所有内容.你现在可以使用匿名类来做到这一点,但适当的关闭至少会削减很多锅炉板.
我使用的一个框架使用类似于这种方法来删除大量样板的东西是Spring-Jdbc.在这里,您将JdbcTemplate传递给一个简单的函数,该函数将您的对象从您的对象中删除,ResultSet并将其与您的查询一起传递给它template.query().这减少了许多恶化和通常的JDBC代码的不可读性.如果你要保持这样的话,肯定会获胜.
IMO,即使有更多的代码行,transform在您的特定示例中,该版本看起来也更具可读性。为什么?因为这个词,转变。您立即知道集合中正在执行转换,而对于普通版本,您必须遵循代码流才能理解其意图。一旦掌握了这些新结构,您就会发现它们更具可读性。
| 归档时间: |
|
| 查看次数: |
857 次 |
| 最近记录: |