摘要:面向?qū)ο蟪R姷脑O(shè)計模式有策略模式模板方法觀察者模式責(zé)任鏈模式以及工廠模式,使用表達(dá)式函數(shù)式編程思維有助于避免面向?qū)ο箝_發(fā)中的那些固定代碼。
本文是一篇《Java 8實戰(zhàn)》的閱讀筆記,閱讀大約需要5分鐘。
有點標(biāo)題黨,但是這確實是我最近使用Lambda表達(dá)式的感受。設(shè)計模式是過去的一些好的經(jīng)驗和套路的總結(jié),但是好的語言特性可以讓開發(fā)者不去考慮這些設(shè)計模式。面向?qū)ο蟪R姷脑O(shè)計模式有策略模式、模板方法、觀察者模式、責(zé)任鏈模式以及工廠模式,使用Lambda表達(dá)式(函數(shù)式編程思維)有助于避免面向?qū)ο箝_發(fā)中的那些固定代碼。下面我們挑選了策略模式和職責(zé)鏈模式兩個案例進(jìn)行分析。
案例1:策略模式當(dāng)我們解決一個問題有不同的解法的時候,又不希望客戶感知到這些解法的細(xì)節(jié),這種情況下適合使用策略模式。策略模式包括三個部分:
解決問題的算法(上圖中的Strategy);
一個或多個該類算法的具體實現(xiàn)(上圖中的ConcreteStrategyA、ConcreteStrategyB和ConcreteStrategyC)
一個或多個客戶使用場景(上圖中的ClientContext)
面向?qū)ο笏悸?/b>首先定義策略接口,表示排序策略:
public interface ValidationStrategy { boolean execute(String s); }
然后定義具體的實現(xiàn)類(即不同的排序算法):
public class IsAllLowerCase implements ValidationStrategy { @Override public boolean execute(String s) { return s.matches("[a-z]+"); } } public class IsNumberic implements ValidationStrategy { @Override public boolean execute(String s) { return s.matches("d+"); } }
最后定義客戶使用場景,代碼如下圖所示。Validator是為客戶提供服務(wù)時使用的上下文環(huán)境,每個Valiator對象中都封裝了具體的Strategy對象,在實際工作中,我們可以通過更換具體的Strategy對象來進(jìn)行客戶服務(wù)的升級,而且不需要讓客戶進(jìn)行升級。
public class Validator { private final ValidationStrategy strategy; public Validator(ValidationStrategy strategy) { this.strategy = strategy; } /** * 給客戶的接口 */ public boolean validate(String s) { return strategy.execute(s); } } public class ClientTestDrive { public static void main(String[] args) { Validator numbericValidator = new Validator(new IsNumberic()); boolean res1 = numbericValidator.validate("7780"); System.out.println(res1); Validator lowerCaseValidator = new Validator(new IsAllLowerCase()); boolean res2 = lowerCaseValidator.validate("aaaffffd"); System.out.println(res2); } }函數(shù)式編程思路
如果使用Lambda表達(dá)式考慮,你會發(fā)現(xiàn)ValidationStrategy就是一個函數(shù)接口(還與Predicate
public class ClientTestDrive { public static void main(String[] args) { Validator numbericValidator = new Validator((String s) -> s.matches("d+")); boolean res1 = numbericValidator.validate("7789"); System.out.println(res1); Validator lowerCaseValidator = new Validator((String s) -> s.matches("[a-z]+")); boolean res2 = lowerCaseValidator.validate("aaaffffd"); System.out.println(res2); } }案例2:責(zé)任鏈模式
在某些場景下,需要對一個對象做一系列的工作,這些工作分別是由不同的類完成的,這時候就比較適合使用責(zé)任鏈模式。責(zé)任鏈模式的主要組成部分包括三個:
管理操作序列的抽象類,在該抽象類里有會有一個對象記錄當(dāng)前對象的后繼操作對象;
一些具體的操作對象,這些操作對象會以一個鏈表的形式組織起來
一個使用該模式的客戶端組件,該組件只需要跟一個組件打交道就好,不需要跟很多個操作對象耦合在一起。
面向?qū)ο笏悸?/b>首先看下我們這里定義了一個抽象類ProcessingObject,其中successor字段用于管理該對象的后繼操作對象;handle接口作為對外提供服務(wù)的接口;handleWork作為實際處理對象的操作方法。
public abstract class ProcessingObject{ protected ProcessingObject successor; public void setSuccessor(ProcessingObject successor) { this.successor = successor; } public T handler(T input) { T r = handleWork(input); if (successor != null) { return successor.handler(r); } return r; } abstract protected T handleWork(T input); }
接下來可以定義兩個具體的操作對象,如下面代碼所示。PS:這里《Java 8實戰(zhàn)》書中用的是replaceAll方法是不太合適的,這個點可以參考我們之前的文章——020:舉幾個String的API以及案例
)。
public class HeaderTextProcessing extends ProcessingObject{ @Override protected String handleWork(String input) { return "From Raoul, Mario and Alan: " + input; } } public class SpellCheckerProcessing extends ProcessingObject { @Override protected String handleWork(String input) { return input.replace("labda", "lambda"); } }
最后,你就可以在Client中將這上面兩個具體的操作類對象構(gòu)成一個操作序列,參見下面的代碼:
public class Client { public static void main(String[] args) { ProcessingObject函數(shù)式編程思路p1 = new HeaderTextProcessing(); ProcessingObject p2 = new SpellCheckerProcessing(); p1.setSuccessor(p2); String result = p1.handler("Aren"t labdas really sexy?!!"); System.out.println(result); } }
如果使用函數(shù)式編程思維,那么職責(zé)鏈模式就直接了——y=f(x)和z=g(x)這兩個方法都是要對x做處理,那么如果將這兩個函數(shù)組合在一起,就會形成r=f(g(x))的情況,也就是可以使用Lambda表達(dá)式中的addThen來串聯(lián)起多個處理過程。
public class ClientWithLambda { public static void main(String[] args) { UnaryOperatorheaderProcessing = (String text) -> "From Raoul, Mario and Alan: " + text; UnaryOperator spellCheckProcessing = (String text) -> text.replace("labda", "lambda"); Function function = headerProcessing.andThen(spellCheckProcessing); String result = function.apply("Aren"t labdas really sexy?!!"); System.out.println(result); UnaryOperator hhhhhProcessing = (String text) -> text.concat("hhhh"); Function function1 = function.andThen(hhhhhProcessing); String result1 = function1.apply("Aren"t labdas really sexy?!!"); System.out.println(result1); } }
上面是利用Java原生的Lambda表達(dá)式實現(xiàn)的職責(zé)鏈模式,我們也可以使用前面一篇文章——vavr:讓你像寫Scala一樣寫Java
)中介紹過的vavr庫來實現(xiàn),代碼如下所示:
public class ClientWithVavr { public static void main(String[] args) { Function1總結(jié)headerProcessing = (String text) -> "From Raoul, Mario and Alan: " + text; Function1 specllCheckProcessing = (String text) -> text.replace("labda", "lambda"); Function1 function = headerProcessing.compose(specllCheckProcessing); String result = function.apply("Aren"t labdas really sexy?!!"); System.out.println(result); } }
可以看出,函數(shù)式編程思維跟面向?qū)ο缶幊趟季S的思考方式是不同的,表達(dá)力更強,因此,作為開發(fā)者是時候認(rèn)真學(xué)習(xí)下函數(shù)式編程思維了,作為Java開發(fā)者,我準(zhǔn)備先從Lambda表達(dá)式開始學(xué)起,然后嘗試學(xué)習(xí)下Scala或Kotlin兩門語言中的函數(shù)式變成特性。
參考資料《Java編程實戰(zhàn)》
《設(shè)計模式之禪》
本號專注于后端技術(shù)、JVM問題排查和優(yōu)化、Java面試題、個人成長和自我管理等主題,為讀者提供一線開發(fā)者的工作和成長經(jīng)驗,期待你能在這里有所收獲。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/75187.html
摘要:它大致概述并討論了前端工程的實踐如何學(xué)習(xí)它,以及在年實踐時使用什么工具。目的是每年發(fā)布一次內(nèi)容更新。前端實踐第一部分廣泛描述了前端工程的實踐。對大多數(shù)人來說,函數(shù)式編程看起來更加自然。 1 Front-End Developer Handbook 2017 地址:https://frontendmasters.com/b... 這是任何人都可以用來了解前端開發(fā)實踐的指南。它大致概述并...
摘要:它大致概述并討論了前端工程的實踐如何學(xué)習(xí)它,以及在年實踐時使用什么工具。目的是每年發(fā)布一次內(nèi)容更新。前端實踐第一部分廣泛描述了前端工程的實踐。對大多數(shù)人來說,函數(shù)式編程看起來更加自然。 1 Front-End Developer Handbook 2017 地址:https://frontendmasters.com/b... 這是任何人都可以用來了解前端開發(fā)實踐的指南。它大致概述并...
摘要:它大致概述并討論了前端工程的實踐如何學(xué)習(xí)它,以及在年實踐時使用什么工具。目的是每年發(fā)布一次內(nèi)容更新。前端實踐第一部分廣泛描述了前端工程的實踐。對大多數(shù)人來說,函數(shù)式編程看起來更加自然。 1 Front-End Developer Handbook 2017 地址:https://frontendmasters.com/b... 這是任何人都可以用來了解前端開發(fā)實踐的指南。它大致概述并...
摘要:前言月份開始出沒社區(qū),現(xiàn)在差不多月了,按照工作的說法,就是差不多過了三個月的試用期,準(zhǔn)備轉(zhuǎn)正了一般來說,差不多到了轉(zhuǎn)正的時候,會進(jìn)行總結(jié)或者分享會議那么今天我就把看過的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開始出沒社區(qū),現(xiàn)在差不多9月了,按照工作的說法,就是差不多過了三個月的試用期,準(zhǔn)備轉(zhuǎn)正了!一般來說,差不多到了轉(zhuǎn)正的時候,會進(jìn)行總結(jié)或者分享會議!那么今天我就...
閱讀 2013·2021-10-12 10:12
閱讀 3137·2019-08-30 15:44
閱讀 895·2019-08-30 15:43
閱讀 3059·2019-08-30 14:02
閱讀 2158·2019-08-30 12:54
閱讀 3566·2019-08-26 17:05
閱讀 2054·2019-08-26 13:34
閱讀 1108·2019-08-26 11:54