日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

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

發布時間:2023/12/3 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 功能Java示例 第6部分–用作参数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是稱為“ 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使用它時都會產生其他結果。 除非我將其設為不可變的,否則將阻止引用的更新。 我告訴過你可能會很棘手

是否可以像上一期中使用isImportant , setToProcessed和setToFailed方法一樣使handle pure ?

在這種情況下,我們必須將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表示接受一個參數并返回結果的函數
  • …和更多

這意味著,我們不需要每次都需要一個函數“接受一個參數并返回結果”時就定義一個特定的接口,例如ResourceCreator - Function已經是一個我們可以利用的接口!

這就是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,并盡可能重用它們。 他們每個人都有泛型類型(如T和R可以由你來表明在發生什么,什么來的函數的輸出 )。

現在,完整的代碼如下所示:

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示例 第6部分–用作参数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。