对象作为参数示例java

这是称为“ Functional Java by Example”的系列文章的第6部分。

我在本系列的每个部分中开发的示例是某种“提要处理程序”,用于处理文档。 在前面的部分,我们试图通过移动尽可能多的副作用,如IO,该系统的外部,以使我们的可能的功能。

现在,我们将一些抽象替换为函数,以作为参数传递。

如果您是第一次来,最好是从头开始阅读。 它有助于了解我们从何处开始以及如何在整个系列中继续前进。

这些都是这些部分:

  • 第1部分–从命令式到声明式
  • 第2部分–讲故事
  • 第3部分–不要使用异常来控制流程
  • 第4部分–首选不变性
  • 第5部分–将I / O移到外部
  • 第6部分–用作参数
  • 第7部分–将失败也视为数据
  • 第8部分–更多纯函数

我将在每篇文章发表时更新链接。 如果您通过内容联合组织来阅读本文,请查看我博客上的原始文章。

每次代码也被推送到这个GitHub项目 。

OO型协作者

还记得我们以前留下的东西吗?

class FeedHandler {Webservice webserviceList<Doc> handle(List<Doc> changes) {changes.findAll { doc -> isImportant(doc) }.collect { doc ->createResource(doc).thenApply { resource ->setToProcessed(doc, resource)}.exceptionally { e ->setToFailed(doc, e)}.get()}}private CompletableFuture<Resource> createResource(doc) {webservice.create(doc)}private static boolean isImportant(doc) {doc.type == 'important'}private static Doc setToProcessed(doc, resource) {doc.copyWith(status: 'processed',apiId: resource.id)}private static Doc setToFailed(doc, e) {doc.copyWith(status: 'failed',error: e.message)}}

上面的提要处理程序需要一个“ Web服务”来完成其工作。

请看以下部分,其中使用WebService类型的协作者来创建基于文档的资源:

class FeedHandler {Webservice webserviceList<Doc> handle(List<Doc> changes) {changes.collect { doc ->createResource(doc)...}private CompletableFuture<Resource> createResource(doc) {webservice.create(doc)}}

请记住, 作为异常处理机制的一部分,我们将其包装在CompletableFuture ,而不是直接返回资源。

如果我们想要WebService以外的其他资源来创建资源怎么办?

好吧,这是同时变得棘手和容易的地方-OO风格可能与FP风格有些冲突。

您会看到, WebService是一个Java接口,定义如下:

interface Webservice {CompletableFuture<Resource> create(Doc doc)
}

这遵循了Dependency Inversion Principle(DIP) ,它是Robert C. Martin提倡的SOLID设计原则的一部分,(其中包括):

抽象不应依赖细节。 细节应取决于抽象。

WebService已经是任何类型的Webservice 实现的抽象。 因此,系统可以具有此接口的多种实现,例如REST实现和SOAP实现:

class RestWebService implements Webservice {@OverrideCompletableFuture<Resource> create(Doc doc) {// do REST communication}
}
class SoapWebService implements Webservice {@OverrideCompletableFuture<Resource> create(Doc doc) {// do SOAP communication}
}

提要处理程序不关心细节 ,它只需要遵守WebService接口定义的协定的东西:有一个create方法可以接受Doc并返回CompletableFuture

FeedHandler类具有一个webservice属性,其中包含对WebService的引用。 任何OO开发人员都可以识别这种样式,因为它非常熟悉:所有协作者都存在于属性中,这些属性(通常)是在构造过程中初始化的。

一旦构造了FeedHandler ,就可以通过DI框架或普通的手工方法将传递的WebService实例传递给它-尽管可以使用构造函数注入或属性注入。

为了简洁起见,我一直在代码片段中省略了构造函数,但是正如您在测试用例中所看到的那样, 我绝对使用Groovy为我生成的构造函数传递所有依赖关系。

协作者FP风格

好的,如果我们再次戴上Functional Hat,我们将需要重新审视将WebService传递到提要处理程序的方式。

handle方法的签名不提比其他任何东西:文件进去 ,文件出来

class FeedHandler {...List<Doc> handle(List<Doc> changes) {...}}

我不能假定将返回相同的输入 相同的输出 -因为该方法暗中依赖于外的东西:对WebService

好吧,也许我可以控制供稿处理程序的整个创建过程,包括WebService ,但是在方法调用之间可以更改对webservice引用,每次handle使用它时都会产生其他结果。 除非我将其设为不可变的,否则将阻止引用的更新。 我告诉过你可能会很棘手

是否可以像上一期中使用isImportantsetToProcessedsetToFailed方法一样使纯正的 handle

在这种情况下,我们必须将WebService作为参数传递,就像传递文档列表一样。

我们改变

class FeedHandler {Webservice webserviceList<Doc> handle(List<Doc> changes) {...}}

进入

class FeedHandler {List<Doc> handle(List<Doc> changes, Webservice webservice) {...}}

在每次调用handle我们都会传递它需要的所有内容:需要处理的文档和需要使用的Web服务。

由于此方法不再依赖于FeedHandler类中的任何属性,因此我们现在可以使其变为static -将其升级为类级方法。

高阶函数

实际上,我们的handle方法刚刚变成了所谓的“高阶函数”,即接受一个函数或返回一个函数的函数。

因此,回到开始时我提出的一个问题: 如果我们想要WebService以外的其他东西来创建资源该怎么办?

它甚至不应该是Web服务吗? 也许我们完全想吃香蕉,一只猴子为我们创造资源?

class Monkey implements Webservice {@OverrideCompletableFuture<Resource> create(Doc doc) {// go bananas! But do create resources plz}
}

看起来很奇怪,不是吗? 对于抽象提要处理程序的需要, WebService接口太具体了。 任何创造资源的东西都会起作用,不是吗?

更好的名称是“ ResourceCreator” ,因此只需重命名接口即可。

旧:

interface Webservice {CompletableFuture<Resource> create(Doc doc)
}

新:

interface ResourceCreator {CompletableFuture<Resource> create(Doc doc)
}

具有create方法的ResourceCreator接口; 多么合身! 现在任何东西都可以实现此接口,并且提要处理程序甚至不在乎它是Web服务,猴子还是霍比特人。

新方法签名:

class FeedHandler {List<Doc> handle(List<Doc> changes, ResourceCreator creator) {...}}

完美的抽象!

功能抽象

在Java中,我们将只有一种抽象方法接口称为功能接口 。 我们的ResourceCreator符合此描述; 它具有单个抽象方法create

Java的java.util.function程序包具有许多这些功能接口,并且每个功能接口都有一个已定义的用途:

  • Consumer表示一个接受参数且不返回任何内容的函数
  • Supplier表示不接受任何参数的函数,仅返回结果
  • Function表示接受一个参数并返回结果的函数
  • …和更多

这意味着,我们不需要每次都需要一个函数“接受一个参数并返回结果”时就定义一个特定的接口,例如ResourceCreatorFunction已经是一个我们可以利用的接口!

这就是Java 8中的Function (简体)的样子:

interface Function<T,R> {R apply(T t);
}

这就是ResourceCreator现在的样子:

interface ResourceCreator {CompletableFuture<Resource> create(Doc doc)
}

您会看到,如果满足以下条件,我们可以用Function完全替代ResourceCreator

  • Doc代替R
  • T型替代CompletableFuture
  • 替代调用create由该方法apply

我们可以完全删除ResourceCreator界面!

新方法签名将变为:

class FeedHandler {List<Doc> handle(List<Doc> changes,Function<Doc, CompletableFuture<Resource>> creator) {...}}

我们取得了什么成就?

  • 我们现在可以传递任何要handle 函数 ,该函数需要一个Doc并产生一个CompletableFuture —这就是feed处理程序正常工作所需的全部。
  • 正如您现在可能已经注意到的,函数编程处理了很多函数 。 一个函数可以采用另一个函数,也可以返回一个函数。
  • 从Java 8开始,我们已经准备好了很多功能接口。 每个开发人员都可以以标准化的方式与他们合作,因此最好查看它们是否适合您的用例和API,并尽可能重用它们。 他们每个人都有泛型类型(如TR可以由你来表明发生什么,什么来的函数的输出 )。

现在,完整的代码如下所示:

class FeedHandler {List<Doc> handle(List<Doc> changes,Function<Doc, CompletableFuture<Resource>> creator) {changes.findAll { doc -> isImportant(doc) }.collect { doc ->creator.apply(doc).thenApply { resource ->setToProcessed(doc, resource)}.exceptionally { e ->setToFailed(doc, e)}.get()}}private static boolean isImportant(doc) {doc.type == 'important'}private static Doc setToProcessed(doc, resource) {doc.copyWith(status: 'processed',apiId: resource.id)}private static Doc setToFailed(doc, e) {doc.copyWith(status: 'failed',error: e.message)}}

现在就这样! 下次,我们将处理故障数据。

如果您有任何意见或建议,我很想听听他们的意见!

翻译自: https://www.javacodegeeks.com/2018/12/functional-java-functions-parameters.html

对象作为参数示例java

对象作为参数示例java_功能Java示例 第6部分–用作参数相关推荐

  1. 大数据 java 代码示例_功能Java示例 第7部分–将失败也视为数据

    大数据 java 代码示例 这是称为" Functional Java by Example"的系列文章的第7部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序 ...

  2. java 示例_功能Java示例 第4部分–首选不变性

    java 示例 这是称为" Functional Java by Example"的系列文章的第4部分. 在上一部分中,我们讨论了一些副作用,并且我想进一步详细说明如何通过将不可变 ...

  3. java 示例_功能Java示例 第2部分–讲故事

    java 示例 这是称为" Functional Java by Example"的系列文章的第2部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序" ...

  4. java 函数式编程 示例_功能Java示例 第1部分–从命令式到声明式

    java 函数式编程 示例 功能编程(FP)的目的是避免重新分配变量,避免可变的数据结构,避免状态并全程支持函数. 如果将功能性技术应用于日常Java代码,我们可以从FP中学到什么? 在这个名为&qu ...

  5. java 函数式编程 示例_功能Java示例 第8部分–更多纯函数

    java 函数式编程 示例 这是第8部分,该系列的最后一部分称为"示例功能Java". 我在本系列的每个部分中开发的示例是某种"提要处理程序",用于处理文档. ...

  6. java 示例_功能Java示例 第5部分–将I / O移到外部

    java 示例 这是称为" Functional Java by Example"的系列文章的第5部分. 在上一部分中,我们停止了对文档的变异,并返回了数据的副本. 现在,我们需要 ...

  7. java 示例_功能Java示例 第3部分–不要使用异常来控制流程

    java 示例 这是称为" Functional Java by Example"的系列文章的第3部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序" ...

  8. 功能Java示例 第6部分–用作参数

    这是称为" Functional Java by Example"的系列文章的第6部分. 我在本系列的每个部分中发展的示例是某种"提要处理程序",用于处理文档. ...

  9. 功能Java示例 第7部分–将失败也视为数据

    这是称为" Functional Java by Example"的系列文章的第7部分. 我在本系列的每个部分中发展的示例是某种"提要处理程序",用于处理文档. ...

最新文章

  1. Python基础总结(3)
  2. 关于expanded一级二级菜单数据的分组排序
  3. 【震惊】史上最牛的市场推广/营销
  4. java class is frozen_利用javassit简单操作class文件 1
  5. HR面 - 十大经典提问
  6. vue编写to-do list源码
  7. [BZOJ2152]聪聪可可(点分治)
  8. 数据链路层的是三个基本问题
  9. CCF201803-4 棋局评估(100分)【博弈+DFS】
  10. zipfian 参数是什么 Zipfian distribution 齐夫定律
  11. cdn 阿里cdn请求原理以及缓存机制
  12. zotero中的标准和规范应该用什么类型
  13. 第16周收录103起融资,芯片创企为热点丨潜在周波啊
  14. 嬴彻科技日: 发布《自动驾驶卡车量产白皮书》分享从量产走向无人技术路线
  15. 技术问答-18 设计模式
  16. 如何用gitbook写书
  17. CCF推荐|中科院2区生物信息与计算机类SCI征稿~
  18. 使用Sendinput函数模拟鼠标键盘操作
  19. 搞日租房的Airbnb,如何用机器学习对接上百万的房东和租客?
  20. excle报盘之导出处理失败数据

热门文章

  1. 2021牛客NOIP提高组第二场T2——方格计数(组合数计数)
  2. 1.16 模拟(排序)
  3. YbtOJ-连通的图【结论,线性基】
  4. 2021牛客OI赛前集训营-交替【生成函数】
  5. P6793-[SNOI2020]字符串【广义SAM,贪心】
  6. P3243-[HNOI2015]菜肴制作【拓扑排序,优先队列】
  7. P5091-[模板]欧拉定理
  8. SpringCloud Zuul(七)之POST Filter
  9. Spring Boot 自动配置的 “魔法” 是如何实现的?
  10. JavaFX官方教程(十四)之转换,动画和视觉效果教程的源代码