日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

学妹惊呼:使用Java8改造后的模板方法模式真的是yyds

發(fā)布時(shí)間:2025/3/16 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 学妹惊呼:使用Java8改造后的模板方法模式真的是yyds 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

△Hollis, 一個(gè)對(duì)Coding有著獨(dú)特追求的人△

這是Hollis的第?371?篇原創(chuàng)分享

作者 l Hollis

來(lái)源 l Hollis(ID:hollischuang)

我們?cè)谌粘i_發(fā)中,經(jīng)常會(huì)遇到類似的場(chǎng)景:當(dāng)要做一件事兒的時(shí)候,這件事兒的步驟是固定好的,但是每一個(gè)步驟的具體實(shí)現(xiàn)方式是不一定的。

通常,遇到這種情況,我們會(huì)把所有要做的事兒抽象到一個(gè)抽象類中,并在該類中定義一個(gè)模板方法。這就是所謂的模板方法模式。

以前的模板方法

在我之前的一篇《設(shè)計(jì)模式——模板方法設(shè)計(jì)模式》https://www.hollischuang.com/archives/420 文章中舉過(guò)一個(gè)例子:

當(dāng)我們?nèi)ャy行的營(yíng)業(yè)廳辦理業(yè)務(wù)需要以下步驟:1.取號(hào)、2.辦業(yè)務(wù)、3.評(píng)價(jià)。

三個(gè)步驟中取號(hào)和評(píng)價(jià)都是固定的流程,每個(gè)人要做的事兒都是一樣的。但是辦業(yè)務(wù)這個(gè)步驟根據(jù)每個(gè)人要辦的事情不同所以需要有不同的實(shí)現(xiàn)。

我們可以將整個(gè)辦業(yè)務(wù)這件事兒封裝成一個(gè)抽象類:

/***?模板方法設(shè)計(jì)模式的抽象類*?@author?hollis*/public?abstract?class?AbstractBusinessHandler?{/***?模板方法*/public?final?void?execute(){getNumber();handle();judge();}/***?取號(hào)*?@return*/private?void?getNumber(){System.out.println("number-00"?+?RandomUtils.nextInt());}/***?辦理業(yè)務(wù)*/public?abstract?void?handle();?//抽象的辦理業(yè)務(wù)方法,由子類實(shí)現(xiàn)/***?評(píng)價(jià)*/private?void?judge(){System.out.println("give?a?praised");}}

我們?cè)陬愔卸x了一個(gè)execute類,這個(gè)類編排了getNumber、handle和judge三個(gè)方法。這就是一個(gè)模板方法

其中g(shù)etNumber和judge都有通用的實(shí)現(xiàn),只有handle方法是個(gè)抽象的,需要子類根據(jù)實(shí)際要辦的業(yè)務(wù)的內(nèi)容去重寫。

有了這個(gè)抽象類和模板方法,當(dāng)我們想要實(shí)現(xiàn)一個(gè)"存錢業(yè)務(wù)"的時(shí)候,只需要繼承該AbstractBusinessHandeler并且重寫handle方法即可:

public?class?SaveMoneyHandler?extends?AbstractBusinessHandeler?{@Overridepublic?void?handle()?{System.out.println("save?1000");}}

這樣,我們?cè)趫?zhí)行存錢的業(yè)務(wù)邏輯的時(shí)候,只需要調(diào)用 SaveMoneyHandler的execute方法即可:

public?static?void?main(String?[]args){SaveMoneyHandler?saveMoneyHandler?=?new?SaveMoneyHandler();saveMoneyHandler.execute();}

輸出結(jié)果:

number-00958442164save?1000give?a?praised

以上,就是一個(gè)簡(jiǎn)單的模板方法的實(shí)現(xiàn)。通過(guò)使用模板方法,可以幫助我們很大程度的復(fù)用代碼。

因?yàn)槲覀円阢y行辦理很多業(yè)務(wù),所以可能需要定義很多的實(shí)現(xiàn)類:

//取錢業(yè)務(wù)的實(shí)現(xiàn)類public?class?DrawMoneyHandler?extends?AbstractBusinessHandeler?{@Overridepublic?void?handle()?{System.out.println("draw?1000");}}//理財(cái)業(yè)務(wù)的實(shí)現(xiàn)類public?class?MoneyManageHandler?extends?AbstractBusinessHandeler{@Overridepublic?void?handle()?{System.out.println("money?manage");}}

一直以來(lái),開發(fā)者們?cè)谑褂媚0宸椒ǖ臅r(shí)候基本都是像上面這個(gè)例子一樣:需要準(zhǔn)備一個(gè)抽象類,將部分邏輯以具體方法以及具體構(gòu)造函數(shù)的形式實(shí)現(xiàn),然后聲明一些抽象方法來(lái)讓子類實(shí)現(xiàn)剩余的邏輯。不同的子類可以以不同的方式實(shí)現(xiàn)這些抽象方法,從而對(duì)剩余的邏輯有不同的實(shí)現(xiàn)。

但是,有了Java 8以后,模板方法有了另外一種實(shí)現(xiàn)方式,不需要定義特別多的實(shí)現(xiàn)類了。

Java 8 的函數(shù)式編程

2014年,Oracle發(fā)布了 Java 8,在Java 8中最大的新特性就是提供了對(duì)函數(shù)式編程的支持。

Java 8在java.util.function下面增加增加一系列的函數(shù)接口。其中主要有Consumer、Supplier、Predicate、Function等。

本文主要想要介紹一下Supplier和Consumer這兩個(gè),使用者兩個(gè)接口,可以幫我們很好的改造模板方法。這里只是簡(jiǎn)單介紹下他們的用法,并不會(huì)深入展開,如果大家想要學(xué)習(xí)更多用法,可以自行g(shù)oogle一下。

Supplier

Supplier是一個(gè)供給型的接口,簡(jiǎn)單點(diǎn)說(shuō),這就是一個(gè)返回某些值的方法。

最簡(jiǎn)單的一個(gè)Supplier就是下面這段代碼:

public?List<String>?getList()?{return?new?ArrayList();}

使用Supplier表示就是:

Supplier<List<String>>?listSupplier?=?ArrayList::new;

Consumer

Consumer 接口消費(fèi)型接口,簡(jiǎn)單點(diǎn)說(shuō),這就是一個(gè)使用某些值(如方法參數(shù))并對(duì)其進(jìn)行操作的方法。

最簡(jiǎn)單的一個(gè)Consumer就是下面這段代碼:

public?void?sum(String?a1)?{System.out.println(a1);}

使用Consumer表示就是:

Consumer<String>?printConsumer?=?a1?->?System.out.println(a1);

Consumer的用法,最見的的例子就是是Stream.forEach(Consumer)這樣的用法,

它接受一個(gè)Consumer,該Consumer消費(fèi)正在迭代的流中的元素,并對(duì)每個(gè)元素執(zhí)行一些操作,比如打印:

Consumer<String>?stringConsumer?=?(s)?->?System.out.println(s.length());Arrays.asList("ab",?"abc",?"a",?"abcd").stream().forEach(stringConsumer);

Java 8以后的模板方法

在介紹過(guò)了Java 8中的Consumer、Supplier之后,我們來(lái)看下怎么改造之前我們介紹過(guò)的模板方法。

首先,我們定義一個(gè)BankBusinessHandler類,并且重新定義一個(gè)execute方法,這個(gè)方法有一個(gè)入?yún)?#xff0c;是Consumer類型的,然后移除handle方法,重新編排后的模板方法內(nèi)容如下:

/***?@author?Hollis*/public?class?BankBusinessHandler?{private?void?execute(Consumer<BigDecimal>?consumer)?{getNumber();consumer.accept(null);judge();}private?void?getNumber()?{System.out.println("number-00"?+?RandomUtils.nextInt());}private?void?judge()?{System.out.println("give?a?praised");}}

我們實(shí)現(xiàn)的模板方法execute中,編排了getNumber、judge以及consumer.accept,這里面consumer.accept就是具體的業(yè)務(wù)邏輯,可能是存錢、取錢、理財(cái)?shù)取P枰善渌椒ㄕ{(diào)用execute的時(shí)候傳入。

這時(shí)候,我們想要實(shí)現(xiàn)"存錢"業(yè)務(wù)的時(shí)候,需要BankBusinessHandler類中增加以下方法:

/***?@author?Hollis*/public?class?BankBusinessHandler?{public?void?save(BigDecimal?amount)?{execute(a?->?System.out.println("save?"?+?amount));}}

在save方法中,調(diào)用execute方法,并且在入?yún)⑻巶魅胍粋€(gè)實(shí)現(xiàn)了"存錢"的業(yè)務(wù)邏輯的Comsumer。

這樣,我們?cè)趫?zhí)行存錢的業(yè)務(wù)邏輯的時(shí)候,只需要調(diào)用 BankBusinessHandler的save方法即可:

public?static?void?main(String[]?args)?throws?{BankBusinessHandler?businessHandler?=?new?BankBusinessHandler();businessHandler.save(new?BigDecimal("1000"));}

輸出結(jié)果:

number-001736151440save1000give?a?praised

如上,當(dāng)我們想要實(shí)現(xiàn)取錢、理財(cái)?shù)葮I(yè)務(wù)邏輯的時(shí)候,和存錢類似:

/***?@author?Hollis*/public?class?BankBusinessHandler?{public?void?save(BigDecimal?amount)?{execute(a?->?System.out.println("save?"?+?amount));}public?void?draw(BigDecimal?amount)?{execute(a?->?System.out.println("draw?"?+?amount));}public?void?moneyManage(BigDecimal?amount)?{execute(a?->?System.out.println("draw?"?+?amount));}}

可以看到,通過(guò)使用Java 8中的Comsumer,我們把模板方法改造了,改造之后不再需要抽象類、抽象方法,也不再需要為每一個(gè)業(yè)務(wù)都創(chuàng)建一個(gè)實(shí)現(xiàn)類了。我們可以把所有的業(yè)務(wù)邏輯內(nèi)聚在同一個(gè)業(yè)務(wù)類中。這樣非常方便這段代碼的后期運(yùn)維。

前面介紹如何使用Consumer進(jìn)行改造模板方法,那么Supplier有什么用呢?

我們的例子中,在取號(hào)、辦業(yè)務(wù)、評(píng)價(jià)這三個(gè)步驟中,辦業(yè)務(wù)是需要根據(jù)業(yè)務(wù)情況進(jìn)行定制的,所以,我們?cè)谀0宸椒ㄖ?#xff0c;把辦業(yè)務(wù)這個(gè)作為擴(kuò)展點(diǎn)開放給外部。

有這樣一種情況,那就是現(xiàn)在我們辦業(yè)務(wù)的時(shí)候,取號(hào)的方式也不一樣,可能是到銀行網(wǎng)點(diǎn)取號(hào)、在網(wǎng)上取號(hào)或者銀行客戶經(jīng)理預(yù)約的無(wú)需取號(hào)等。

無(wú)論取號(hào)的方式如何,最終結(jié)果都是取一個(gè)號(hào);而取到的號(hào)的種類不同,可能接收到的具體服務(wù)也不同,比如vip號(hào)會(huì)到VIP柜臺(tái)辦理業(yè)務(wù)等。

想要實(shí)現(xiàn)這樣的業(yè)務(wù)邏輯,就需要使用到Supplier,Supplier是一個(gè)"供給者",他可以用來(lái)定制"取號(hào)邏輯"。

首先,我們需要改造下模板方法:

/***?模板方法*/protected?void?execute(Supplier<String>?supplier,?Consumer<BigDecimal>?consumer)?{String?number?=?supplier.get();System.out.println(number);if?(number.startsWith("vip"))?{//Vip號(hào)分配到VIP柜臺(tái)System.out.println("Assign?To?Vip?Counter");}else?if?(number.startsWith("reservation"))?{//預(yù)約號(hào)分配到專屬客戶經(jīng)理System.out.println("Assign?To?Exclusive?Customer?Manager");}else{//默認(rèn)分配到普通柜臺(tái)System.out.println("Assign?To?Usual?Manager");}consumer.accept(null);judge();}

經(jīng)過(guò)改造,execute的入?yún)⒃黾恿艘粋€(gè)supplier,這個(gè)supplier可以提供一個(gè)號(hào)碼。至于如何取號(hào)的,交給調(diào)用execute的方法來(lái)執(zhí)行。

之后,我們可以定義多個(gè)存錢方法,分別是Vip存錢、預(yù)約存錢和普通存錢:

public?class?BankBusinessHandler?extends?AbstractBusinessHandler?{public?void?saveVip(BigDecimal?amount)?{execute(()?->?"vipNumber-00"?+?RandomUtils.nextInt(),?a?->?System.out.println("save?"?+?amount));}public?void?save(BigDecimal?amount)?{execute(()?->?"number-00"?+?RandomUtils.nextInt(),?a?->?System.out.println("save?"?+?amount));}public?void?saveReservation(BigDecimal?amount)?{execute(()?->?"reservationNumber-00"?+?RandomUtils.nextInt(),?a?->?System.out.println("save?"?+?amount));}}

在多個(gè)不同的存錢方法中,實(shí)現(xiàn)不同的取號(hào)邏輯,把取號(hào)邏輯封裝在supplier中,然后傳入execute方法即可。

測(cè)試代碼如下:

BankBusinessHandler?businessHandler?=?new?BankBusinessHandler();businessHandler.saveVip(new?BigDecimal("1000"));

輸出結(jié)果:

vipNumber-001638110566Assign?To?Vip?Countersave?1000give?a?praised

以上,我們就是用Comsumer和Supplier改造了模板方法模式。

使用Java 8對(duì)模板方法進(jìn)行改造之后,可以進(jìn)一步的減少代碼量,至少可少創(chuàng)建很多實(shí)現(xiàn)類,大大的減少重復(fù)代碼,提升可維護(hù)性。

當(dāng)然,這種做法也不是十全十美的,有一個(gè)小小的缺點(diǎn),那就是理解成本稍微高一點(diǎn),對(duì)于那些對(duì)函數(shù)式編程不太熟悉的開發(fā)者來(lái)說(shuō), 上手成本稍微高了一些。。。

總結(jié)

以上,我們介紹了什么是模板方法模式,以及如何使用Comsumer和Supplier改造模板方法模式。

這樣的做法是我們?nèi)粘i_發(fā)中經(jīng)常會(huì)用到的,其實(shí),我覺得本文中的例子并不是完完全全能表達(dá)出來(lái)我想表達(dá)的意思,但是我們的真實(shí)業(yè)務(wù)中的邏輯講起來(lái)又比較復(fù)雜。

所以,這就需要大家能夠多多理解并且實(shí)踐一下。如果你代碼中用到過(guò)模板方法模式,那一定是可以通過(guò)本文中的方法進(jìn)行改造的。

如果你還沒(méi)用過(guò)模板方法模式,那說(shuō)明你的應(yīng)用中一定有很多重復(fù)代碼,那就趕緊用起來(lái)。

作為一個(gè)開發(fā)工程師,我們要盡最大努力的消滅應(yīng)用中的重復(fù)代碼,功在當(dāng)代,利在千秋!

?

技術(shù)交流群

最近有很多人問(wèn),有沒(méi)有讀者交流群,想知道怎么加入。

最近我創(chuàng)建了一些群,大家可以加入。交流群都是免費(fèi)的,只需要大家加入之后不要隨便發(fā)廣告,多多交流技術(shù)就好了。

目前創(chuàng)建了多個(gè)交流群,全國(guó)交流群、北上廣杭深等各地區(qū)交流群、面試交流群、資源共享群等。

有興趣入群的同學(xué),可長(zhǎng)按掃描下方二維碼,一定要備注:全國(guó) Or 城市 Or 面試 Or 資源,根據(jù)格式備注,可更快被通過(guò)且邀請(qǐng)進(jìn)群。

▲長(zhǎng)按掃描

往期推薦

干掉 Postman?測(cè)試接口直接生成API文檔,這個(gè)工具我愛了


程序員千萬(wàn)不要做舔狗啊!


官方認(rèn)證:軟件及信息技術(shù)從業(yè)者為新生代農(nóng)民工

如果你喜歡本文,

請(qǐng)長(zhǎng)按二維碼,關(guān)注?Hollis.

轉(zhuǎn)發(fā)至朋友圈,是對(duì)我最大的支持。

點(diǎn)個(gè)?在看?

喜歡是一種感覺

在看是一種支持

↘↘↘

總結(jié)

以上是生活随笔為你收集整理的学妹惊呼:使用Java8改造后的模板方法模式真的是yyds的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。