最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

函數(shù)式編程和設(shè)計模式(序章)

2022-07-14 00:21 作者:ZeromaX訸  | 我要投稿


前段時間想起《Java 8 實戰(zhàn)》一書中提到,策略模式、模板模式之類的傳統(tǒng)設(shè)計模式在使用 lambda 進(jìn)行實現(xiàn)時可以很輕松的實現(xiàn),就想針對性的查一下 GoF 的那些設(shè)計模式在函數(shù)式編程的情況下還有什么更好的實現(xiàn)。因此,找到了一本好書——《Scala 和 Clojure 函數(shù)式編程模式》——里面介紹了傳統(tǒng)面向?qū)ο蟮囊恍┰O(shè)計模式在 Scala 和 Clojure 語言中的實現(xiàn),此外還介紹了一下函數(shù)式編程獨特的一些設(shè)計模式。這開拓了我自己的視野,所以打算整理整理一下自己閱讀過程的一些感想,寫成文章給大家分享。

在本篇序章中,我先簡單回顧一下《Java 8 實戰(zhàn)》中提到的幾種在 Java 語言中的可以使用 Lambda 優(yōu)化實現(xiàn)的設(shè)計模式。這里我們不會對具體的設(shè)計模式過多著墨,直接把相關(guān)的普通實現(xiàn)方式和 Lambda 實現(xiàn)方式的對比貼出來。預(yù)計在后續(xù)文章再分享一下結(jié)合我自己以前對設(shè)計模式的學(xué)習(xí),現(xiàn)在又看了《Scala 和 Clojure 函數(shù)式編程模式》一書中的其他啟發(fā)深思的設(shè)計模式實現(xiàn)的讀后感。

下面會介紹的主要包含五個設(shè)計模式:

  • 策略模式

  • 模板模式

  • 觀察者模式

  • 責(zé)任鏈模式

  • 工廠模式

1 策略模式

策略模式簡單來說代表了解決一類算法的通用解決方案,你可以在運行時選擇使用哪種方案。

策略模式包含三部分內(nèi)容:

  • 一個代表某個算法的接口(它是策略模式的接口)

  • 一個或多個該接口的具體實現(xiàn),它們代表了算法的多種實現(xiàn)。

  • 一個或多個使用策略對象的客戶。

例如下面這個例子,我們希望驗證輸入的內(nèi)容是否符合標(biāo)準(zhǔn)(不同的策略,比如只包含小寫字母或數(shù)字)。我們應(yīng)用設(shè)計模式可以有如下代碼實現(xiàn):

如果我們不聲明新的類實現(xiàn)不同的策略,而是直接傳遞 Lambda 表達(dá)式來實現(xiàn),代碼相當(dāng)簡潔。如下所示:

Lambda 表達(dá)式實際上已經(jīng)對部分代碼(或者說策略)進(jìn)行了封裝,而這就是創(chuàng)建策略設(shè)計模式的初衷。

因此《Java 8 實戰(zhàn)》一書中強烈建議對類似問題盡量使用 Lambda 表達(dá)式來解決。

2 模板模式

如果你需要采用某個算法的框架,同時又希望有一定的靈活度,能對它的某些部分進(jìn)行改進(jìn),那么采用模板方法設(shè)計模式是比較通用的方案。換句話說,模板方法模式在你“希望使用這個算法,但是需要對其中的某些行進(jìn)行改進(jìn),才能達(dá)到希望的效果”時是非常有用的。

例如對于一個可以自定義讓用戶滿意的操作的在線銀行應(yīng)用,使用抽象類實現(xiàn)的代碼如下:

大致邏輯就是先按 id 獲取到用戶信息,然后對應(yīng)執(zhí)行讓用戶滿意的操作(makeCustomerHappy 抽象方法)。

使用 Lambda 表達(dá)式同樣可以解決這些問題(創(chuàng)建算法框架,讓具體的實現(xiàn)插入某些部分)。你想要插入的不同算法組件可以通過 Lambda 表達(dá)式或者方法引用的方式實現(xiàn)。代碼如下:

那么通過第二個參數(shù) Consumer<Customer> makeCustomerHappy,你就可以直接將原來抽象方法的邏輯作為 Lambda 表達(dá)式傳入,從而插入不同的行為。從而免去了繼承 OnlineBanking 抽象類的麻煩。使用過程如下面代碼:


3 觀察者模式

觀察者模式是一種比較常見的方案,某些事件發(fā)生時(比如狀態(tài)轉(zhuǎn)變),如果一個對象(通常我們稱之為主題)需要自動地通知其他多個對象(稱為觀察者),就會采用該方案。創(chuàng)建圖形用戶界面(GUI)程序時,你經(jīng)常會使用該設(shè)計模式。這種情況下,你會在圖形用戶界面組件(比如按鈕)上注冊一系列的觀察者。如果點擊按鈕,觀察者就會收到通知,并隨即執(zhí)行某個特定的行為。

接下來所舉的例子是多個新聞媒體監(jiān)聽某一主題的消息的情況。代碼如下:

順便翻譯了一下原書代碼里面玩的梗,哈哈…… 衛(wèi)報(Guardian)會關(guān)注這一則新聞。

這里其實 Lambda 表達(dá)式可以做的優(yōu)化就不是特別多,只是通過將觀察者們提取成 Lambda 表達(dá)式表示需要執(zhí)行的行為。例如衛(wèi)報的邏輯我們可以這樣實現(xiàn):

但觀察者邏輯可能十分復(fù)雜,可能還持有狀態(tài),抑或定義了多個方法。諸如此類情況時,你應(yīng)該繼續(xù)使用類的方式。

4 責(zé)任鏈模式

責(zé)任鏈模式是一種創(chuàng)建處理對象序列(比如操作序列)的通用方案。一個處理對象可能需要在完成一些工作之后,將結(jié)果傳遞給另一個對象,這個對象接著做一些工作,再轉(zhuǎn)交給下一個處理對象,以此類推。

通常,這種模式是通過定義一個代表處理對象的抽象類來實現(xiàn)的,在抽象類中會定義一個字段來記錄后續(xù)對象。一旦對象完成它的工作,處理對象就會將它的工作轉(zhuǎn)交給它的后繼。 代碼中,這段邏輯看起來是下面這樣:

可能你已經(jīng)注意到,這就是第二節(jié)介紹的模板方法設(shè)計模式。 handle 方法提供了如何進(jìn)行工作處理的框架。不同的處理對象可以通過繼承 ProcessingObject 類,提供 handleWork 方法來進(jìn)行創(chuàng)建。

使用的代碼如下:

這個模式看起來就像是在鏈接多個函數(shù)而構(gòu)造一個新的總函數(shù)。那么,我們可以使用 UnaryOperator<String>andThen 方法進(jìn)行構(gòu)造:


5 工廠模式

使用工廠模式,你無需向客戶暴露實例化的邏輯就能完成對象的創(chuàng)建。比如,我們假定你為一家銀行工作,他們需要一種方式創(chuàng)建不同的金融產(chǎn)品:貸款、期權(quán)、股票,等等。

通常,你會創(chuàng)建一個工廠類,它包含一個負(fù)責(zé)實現(xiàn)不同對象的方法,如下所示:

那么,因為方法引用也可以引用構(gòu)造函數(shù),所以我們可以通過這種方式來創(chuàng)建一個 Map,將產(chǎn)品名映射到對應(yīng)的構(gòu)造函數(shù):

上面使用構(gòu)造方法引用達(dá)到了傳統(tǒng)工廠模式同樣的效果。但是,如果工廠方法 createProduct 需要接收多個傳遞給產(chǎn)品構(gòu)造方法的參數(shù),這種方式的擴(kuò)展性不是很好。你不得不提供不同的函數(shù)接口,無法采用之前統(tǒng)一使用一個簡單接口的方式。比如,我們假設(shè)你希望保存具有三個參數(shù)(兩個參數(shù)為 Integer 類型,一個參數(shù)為 String 類型)的構(gòu)造函數(shù);為了完成這個任務(wù),你需要創(chuàng)建一個特殊的函數(shù)接口 TriFunction。最終的結(jié)果是 Map 變得更加復(fù)雜。


6 總結(jié)

從《Java 8 實戰(zhàn)》一書中的 “8.2 使用 Lambda 重構(gòu)面向?qū)ο蟮脑O(shè)計模式”中我們可以看到,很多的設(shè)計模式可以使用 Java 8 中引入的 Lambda 表達(dá)式和方法引用更加簡潔的實現(xiàn)。而對于其他設(shè)計模式,更甚至在函數(shù)式編程被更豐富地支持的 Scala 語言中,會有更多的簡潔實現(xiàn),大大簡化了我們對于設(shè)計模式的識記。某種程度上,也是函數(shù)式編程更高的抽象能力(可以對函數(shù)本身進(jìn)行操作),賦予了我們更強的實現(xiàn)能力。

正如同迭代器模式、原型模式這些在 Java 中因為 Iterator、Cloneable 而實現(xiàn)大大簡化。在函數(shù)式編程特性已經(jīng)開始逐步普及到各個傳統(tǒng)面向?qū)ο笳Z言的今天,我們也許可以更多地“忘記” GoF 的 23 種設(shè)計模式,從而走上一條大道至簡道路。從把書讀厚(不會設(shè)計模式到會設(shè)計模式),到把書讀?。ㄔ賹W(xué)會利用函數(shù)式編程的方法無招勝有招),這也是個有趣的過程。

后續(xù)我會繼續(xù)更新《Scala 和 Clojure 函數(shù)式編程模式》一書相關(guān)以及其他的函數(shù)式編程與設(shè)計模式的話題,并盡量嘗試用 Java 復(fù)刻一下。感興趣也可以繼續(xù)關(guān)注喲~

題外話

在知乎搜索相關(guān)話題時,發(fā)現(xiàn)有一個整理編程界(或者說軟件開發(fā)業(yè)界)類似“設(shè)計模式”的關(guān)注點的列表(已經(jīng)是 2015 年的老回答了:https://www.zhihu.com/question/30190384/answer/47294641):

  1. GoF Patterns 設(shè)計模式

  2. IoC / Container, Application Server (e.g. EJB) 控制反轉(zhuǎn) / 容器、應(yīng)用服務(wù)器

  3. UML / MDA 統(tǒng)一建模語言 / 模型驅(qū)動架構(gòu)

  4. ORM ?對象關(guān)系映射

  5. AOP / Meta-Programming 面向切面編程 / 元編程

  6. SOA 面向服務(wù)架構(gòu)

  7. Concurrency Facility: Fiber, Green-thread / Message Passing Patterns 并發(fā)

  8. Async Facility 異步

  9. NoSQL 非關(guān)系型數(shù)據(jù)庫

  10. Functional Programming / Map-Reduce 函數(shù)式編程

不得不說深有感觸,很多設(shè)計模式也是相應(yīng)問題下積累下來的成熟解決方案。隨著時代的進(jìn)步,舊問題也會有新的解答和應(yīng)用,新的領(lǐng)域也會出現(xiàn)。函數(shù)式編程其實某種程度上也是經(jīng)歷了老樹發(fā)新芽的過程,如今在以前面向?qū)ο蟮恼Z言上也逐步出現(xiàn)了函數(shù)式編程的新特性。不得不說學(xué)無止境啊……


函數(shù)式編程和設(shè)計模式(序章)的評論 (共 條)

分享到微博請遵守國家法律
枣阳市| 涞水县| 扶沟县| 汽车| 文山县| 棋牌| 乐陵市| 仁化县| 北流市| 舞阳县| 六安市| 芷江| 延安市| 彭州市| 恩平市| 丹江口市| 方城县| 东港市| 英超| 青铜峡市| 罗江县| 泗水县| 巴彦淖尔市| 涞源县| 福鼎市| 曲阳县| 蕉岭县| 宣化县| 凌海市| 明光市| 迭部县| 潍坊市| 中西区| 麻城市| 芷江| 屏东市| 鄢陵县| 阿图什市| 广西| 迁西县| 阳山县|