最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Java8實(shí)現(xiàn)模板方法模式的改造

 更新時(shí)間:2023年01月30日 11:22:36   作者:Hollis  
這篇文章主要為大家詳細(xì)介紹了如何使用Java8實(shí)現(xiàn)模板方法模式的改造,文中的示例代碼講解詳細(xì),對(duì)我們深入了解java8有一定的幫助,感興趣的可以了了解一下

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

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

以前的模板方法

在我之前的一篇《設(shè)計(jì)模式——模板方法設(shè)計(jì)模式》文章中舉過一個(gè)例子:

當(dāng)我們?nèi)ャy行的營業(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 {

    @Override

    public 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-00958442164

save 1000

give a praised

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

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

//取錢業(yè)務(wù)的實(shí)現(xiàn)類

public class DrawMoneyHandler extends AbstractBusinessHandeler {

    @Override

    public void handle() {

        System.out.println("draw 1000");

    }

}

//理財(cái)業(yè)務(wù)的實(shí)現(xiàn)類

public class MoneyManageHandler extends AbstractBusinessHandeler{

    @Override

    public void handle() {

        System.out.println("money manage");

    }

}

一直以來,開發(fā)者們?cè)谑褂媚0宸椒ǖ臅r(shí)候基本都是像上面這個(gè)例子一樣:需要準(zhǔn)備一個(gè)抽象類,將部分邏輯以具體方法以及具體構(gòu)造函數(shù)的形式實(shí)現(xiàn),然后聲明一些抽象方法來讓子類實(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è)接口,可以幫我們很好的改造模板方法。這里只是簡單介紹下他們的用法,并不會(huì)深入展開,如果大家想要學(xué)習(xí)更多用法,可以自行g(shù)oogle一下。

Supplier

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

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

public List<String> getList() {

    return new ArrayList();

}

使用Supplier表示就是:

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

Consumer

Consumer 接口消費(fèi)型接口,簡單點(diǎn)說,這就是一個(gè)使用某些值(如方法參數(shù))并對(duì)其進(jì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í)行一些操作,比如打?。?/p>

Consumer<String> stringConsumer = (s) -> System.out.println(s.length());

Arrays.asList("ab", "abc", "a", "abcd").stream().forEach(stringConsumer);

Java 8以后的模板方法

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

首先,我們定義一個(gè)BankBusinessHandler類,并且重新定義一個(gè)execute方法,這個(gè)方法有一個(gè)入?yún)?,是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ù)?。需要由其他方法調(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-001736151440

save1000

give 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));

    }

}

可以看到,通過使用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宸椒ㄖ?,把辦業(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ù)約的無需取號(hào)等。

無論取號(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è)"供給者",他可以用來定制"取號(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)過改造,execute的入?yún)⒃黾恿艘粋€(gè)supplier,這個(gè)supplier可以提供一個(gè)號(hào)碼。至于如何取號(hào)的,交給調(diào)用execute的方法來執(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方法即可。

測試代碼如下:

BankBusinessHandler businessHandler = new BankBusinessHandler();

businessHandler.saveVip(new BigDecimal("1000"));

輸出結(jié)果:

vipNumber-001638110566

Assign To Vip Counter

save 1000

give 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ā)者來說, 上手成本稍微高了一些。。。

總結(jié)

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

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

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

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

到此這篇關(guān)于使用Java8實(shí)現(xiàn)模板方法模式的改造的文章就介紹到這了,更多相關(guān)Java8改造模板方法模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java Lombok之@Accessors用法及說明

    java Lombok之@Accessors用法及說明

    這篇文章主要介紹了java Lombok之@Accessors用法及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • spring?retry實(shí)現(xiàn)方法請(qǐng)求重試的使用步驟

    spring?retry實(shí)現(xiàn)方法請(qǐng)求重試的使用步驟

    這篇文章主要介紹了spring?retry實(shí)現(xiàn)方法請(qǐng)求重試及使用步驟,本文分步驟通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • java線程池ExecutorService超時(shí)處理小結(jié)

    java線程池ExecutorService超時(shí)處理小結(jié)

    使用ExecutorService時(shí),設(shè)置子線程執(zhí)行超時(shí)是一個(gè)常見需求,本文就來詳細(xì)的介紹一下ExecutorService超時(shí)的三種方法,感興趣的可以了解一下
    2024-09-09
  • 詳解SpringBoot中@SessionAttributes的使用

    詳解SpringBoot中@SessionAttributes的使用

    這篇文章主要通過示例為大家詳細(xì)介紹了SpringBoot中@SessionAttributes的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-07-07
  • 淺析Alibaba Nacos注冊(cè)中心源碼剖析

    淺析Alibaba Nacos注冊(cè)中心源碼剖析

    這篇文章主要介紹了淺析Alibaba Nacos注冊(cè)中心源碼剖析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-05-05
  • 看過就懂的java零拷貝及實(shí)現(xiàn)方式詳解

    看過就懂的java零拷貝及實(shí)現(xiàn)方式詳解

    這篇文章主要為大家詳細(xì)的介紹了什么是零拷貝,傳統(tǒng)的IO執(zhí)行流程,零拷貝相關(guān)的知識(shí)點(diǎn)回顧,零拷貝實(shí)現(xiàn)的幾種方式及java提供的零拷貝方式相關(guān)內(nèi)容,有需要的朋友可以借鑒參考下
    2022-01-01
  • 詳解Spring Boot中Controller用法

    詳解Spring Boot中Controller用法

    Controller是SpringBoot里最基本的組件,他的作用是把用戶提交來的請(qǐng)求通過對(duì)URL的匹配,分配個(gè)不同的接收器,再進(jìn)行處理,然后向用戶返回結(jié)果。下面通過本文給大家介紹Spring Boot中Controller用法,需要的朋友參考下
    2017-05-05
  • SpringBoot實(shí)現(xiàn)服務(wù)接入nacos注冊(cè)中心流程詳解

    SpringBoot實(shí)現(xiàn)服務(wù)接入nacos注冊(cè)中心流程詳解

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)服務(wù)接入nacos注冊(cè)中心流程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-01-01
  • SWT JFace Bookmark 制作

    SWT JFace Bookmark 制作

    SWT JFace Bookmark 制作
    2009-06-06
  • Mybatis映射文件詳解之mapper.xml文件

    Mybatis映射文件詳解之mapper.xml文件

    本文詳細(xì)介紹了Mybatis映射文件的結(jié)構(gòu)、標(biāo)簽和使用方法,包括mapper元素、標(biāo)簽的主要屬性如id、parameterType、resultType以及動(dòng)態(tài)SQL和結(jié)果映射的使用,通過映射文件,可以將數(shù)據(jù)庫表與Java對(duì)象映射,支持查詢、插入、更新、刪除等操作,提高了SQL語句的靈活性和可重用性
    2024-09-09

最新評(píng)論

临朐县| 伊春市| 康马县| 宜宾市| 沙雅县| 新绛县| 阜阳市| 汶上县| 南江县| 达州市| 万盛区| 长沙县| 霍山县| 吕梁市| 双城市| 山西省| 区。| 防城港市| 梁平县| 浏阳市| 五寨县| 砚山县| 英山县| 太仓市| 彩票| 桐柏县| 赣州市| 杭锦旗| 镇原县| 荣成市| 高台县| 鱼台县| 疏附县| 阳春市| 长治市| 台中市| 青川县| 武夷山市| 沁水县| 浮梁县| 田阳县|