Java中的模板模式說明與實(shí)現(xiàn)
1. 模板模式概述
1.1 模板模式介紹
- 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern), 在一個(gè)抽象類公開定義了執(zhí)行它的方法的模板。它的子類可以更需要重寫方法實(shí)現(xiàn),但可以成為典型類中定義的方式進(jìn)行。
- 簡(jiǎn)單說,模板方法模式定義了一個(gè)操作中的算法的核心定義,而將一些步驟遲緩到子類中,模仿子類可以不改變一一個(gè)算法的結(jié)構(gòu),就可以重新定義該算法的部分特定步驟。
- 這些類型的設(shè)計(jì)模式屬于行為型模式。
模板模式適用于通用步驟的操作,比如做菜,不管你是西紅柿炒雞蛋,還是土豆燉牛肉實(shí)現(xiàn)步驟都是一樣的,備料,做菜,上菜。 再比如投放系統(tǒng),不管你是投放巨量引擎,廣點(diǎn)通還是百度,前期工作實(shí)現(xiàn)步驟也都是一樣的,配置物料信息,構(gòu)建投放對(duì)象,投放廣告。
1.2 模板模式類圖
對(duì)原理類圖的說明-即(模板方法模式的角色及職責(zé))
1.AbstractClass 抽象類, 類中實(shí)現(xiàn)了模板方法(template),定義了算法的骨架,具體子類需要去實(shí)現(xiàn) 其它的抽象方法。
2.ConcreteClass 實(shí)現(xiàn)抽象方法, 以完成算法中特點(diǎn)子類的步驟。
1.3 模板方法模式的注意事項(xiàng)和細(xì)節(jié)
- 基本思想是:算法只存在于一個(gè)地方,也就是在父類中,容易修改.需要修改算法時(shí),只要修改父類的模板方 法或者已經(jīng)實(shí)現(xiàn)的某些步驟,子類就會(huì)繼承這些修改
- 實(shí)現(xiàn)了最大化代碼復(fù)用.父類的模板方法和已實(shí)現(xiàn)的某些步驟會(huì)被子類繼承而直接使用
- 既統(tǒng)一了算法,也提供了很大的靈活性.父類的模板方法確保了算法的結(jié)構(gòu)保持不變,同時(shí)由子類提供部分步 驟的實(shí)現(xiàn).
- 該模式的不足之處:每個(gè)不同的實(shí)現(xiàn)都需要一個(gè)子類實(shí)現(xiàn),導(dǎo)致類的個(gè)數(shù)增加,使得系統(tǒng)更加龐大
- 一般模板方法都加上 final 關(guān)鍵字, 防止子類重寫模板方法
- 模板方法模式使用場(chǎng)景:當(dāng)要完成在某個(gè)過程,該過程要執(zhí)行一系列步驟 ,這一系列的步驟基本相同,但其 個(gè)別步驟在實(shí)現(xiàn)時(shí) 可能不同,通??紤]用模板方法模式來處理
2. 模板模式實(shí)現(xiàn)
模板模式實(shí)現(xiàn)案例采用三種方式: 第一案例是做菜,無論做什么菜都是這三個(gè)步驟,備料,做菜,上菜,但是三個(gè)步驟都不相同,模板定義步驟流程,通過不同的子類繼承抽象模板實(shí)現(xiàn)模板設(shè)計(jì)模式。
第二個(gè)案例是銀行辦理業(yè)務(wù),無論辦理什么業(yè)務(wù)都是取號(hào),辦理業(yè)務(wù),評(píng)價(jià)。這里取號(hào)與評(píng)價(jià)都是相同的,各個(gè)子類只需要處理不同業(yè)務(wù)即可,通過不同的子類繼承抽象模板實(shí)現(xiàn)模板設(shè)計(jì)模式。
第三個(gè)案例是銀行辦理業(yè)務(wù)的Java8函數(shù)式編程消費(fèi)者模式Consumer模式改造,原理相同。
2.1 做菜模板模式
DishEggsWithTomato
package com.zrj.design.template.dish; /** * 西紅柿炒雞蛋 * * @author zrj * @since 2022/2/8 */ public class DishEggsWithTomato extends DishTemplate { @Override public void preparation() { System.out.println("準(zhǔn)備西紅柿雞蛋..."); } @Override public void doing() { System.out.println("開始炒西紅柿雞蛋..."); } @Override public void carriedDishes() { System.out.println("西紅柿雞蛋裝盤..."); } }
DishOnionWithTofu
package com.zrj.design.template.dish; /** * 小蔥拌豆腐 * * @author zrj * @since 2022/2/8 */ public class DishOnionWithTofu extends DishTemplate { @Override public void preparation() { System.out.println("準(zhǔn)備小蔥豆腐..."); } @Override public void doing() { System.out.println("開始炒小蔥拌豆腐..."); } @Override public void carriedDishes() { System.out.println("小蔥拌豆腐裝盤..."); } }
DishTemplate
package com.zrj.design.template.dish; /** * 做菜模板類 * 用于定義做菜的執(zhí)行步驟,所有菜都可以按照這種方式做菜 * * @author zrj * @since 2022/2/8 */ public abstract class DishTemplate { /** * 做菜執(zhí)行步驟 */ public final void doDish() { this.preparation(); this.doing(); this.carriedDishes(); } /** * 備料 */ public abstract void preparation(); /** * 做菜 */ public abstract void doing(); /** * 上菜 */ public abstract void carriedDishes(); }
DishTemplateTest
package com.zrj.design.template.dish; import org.junit.Test; /** * 模板模式 * 抽象父類定義方法模板,子類自定義實(shí)現(xiàn)方式。 * 優(yōu)點(diǎn): 1、封裝不變部分,擴(kuò)展可變部分。 2、提取公共代碼,便于維護(hù)。 3、行為由父類控制,子類實(shí)現(xiàn)。 * 缺點(diǎn):每一個(gè)不同的實(shí)現(xiàn)都需要一個(gè)子類來實(shí)現(xiàn),導(dǎo)致類的個(gè)數(shù)增加,使得系統(tǒng)更加龐大。 * 使用場(chǎng)景: 1、有多個(gè)子類共有的方法,且邏輯相同。 2、重要的、復(fù)雜的方法,可以考慮作為模板方法。 * 注意事項(xiàng):為防止惡意操作,一般模板方法都加上 final 關(guān)鍵詞。 * * 使用場(chǎng)景很多,只要有相同的執(zhí)行邏輯,或者重要的復(fù)雜的方法,都可以交給父類管理。 * 比如開發(fā)XX系統(tǒng)步驟都是一樣的,立項(xiàng),需求,開發(fā),測(cè)試,上線。 * * @author zrj * @since 2022/2/8 */ public class DishTemplateTest { @Test public void templateTest() { System.out.println("----------西紅柿炒雞蛋----------"); DishTemplate eggsWithTomato = new DishEggsWithTomato(); eggsWithTomato.doDish(); System.out.println("----------小蔥拌豆腐----------"); DishTemplate onionWithTofu = new DishOnionWithTofu(); onionWithTofu.doDish(); } }
2.2 銀行辦理業(yè)務(wù)模板模式
BankBusinessHandler
package com.zrj.design.template.bank; import cn.hutool.core.util.RandomUtil; /** * 模板方法設(shè)計(jì)模式的抽象類 * 模板設(shè)計(jì)模式主要用來處理相同處理流程中的不同點(diǎn),例如銀行辦理業(yè)務(wù),無論什么業(yè)務(wù),首先需要取號(hào),其次處理業(yè)務(wù),然后評(píng)價(jià)不同之處在于處理不同的業(yè)務(wù)使用不同的方式。 * BankBusinessHandler作為抽象模板 * BankSaveMoneyHandler作為存錢業(yè)務(wù)處理類,繼承抽象模板BankBusinessHandler * BankDrawMoneyHandler作為理財(cái)業(yè)務(wù)處理類,繼承抽象模板BankBusinessHandler * * @author zrj * @since 2022/2/8 **/ public abstract class BankBusinessHandler { /** * 模板方法,執(zhí)行器 */ public final void execute() { getNumber(); handle(); judge(); } /** * 取號(hào) */ private void getNumber() { System.out.println("取號(hào):" + RandomUtil.randomNumbers(8)); } /** * 辦理業(yè)務(wù) */ public abstract void handle(); /** * 評(píng)價(jià) */ private void judge() { System.out.println("評(píng)價(jià):五星好評(píng)!"); } }
BankBusinessHandlerTest
package com.zrj.design.template.bank; /** * 模板方法測(cè)試類 * * @author zrj * @since 2022/2/8 **/ public class BankBusinessHandlerTest { public static void main(String[] args) { //存錢業(yè)務(wù)處理 BankSaveMoneyHandler bankSaveMoneyHandler = new BankSaveMoneyHandler(); bankSaveMoneyHandler.execute(); System.out.println("------------------------------"); //理財(cái)業(yè)務(wù)處理 BankDrawMoneyHandler bankDrawMoneyHandler = new BankDrawMoneyHandler(); bankDrawMoneyHandler.execute(); } }
BankDrawMoneyHandler
package com.zrj.design.template.bank; /** * 理財(cái)業(yè)務(wù) * * @author zrj * @since 2022/2/8 **/ public class BankDrawMoneyHandler extends BankBusinessHandler { /** * 辦理業(yè)務(wù) */ @Override public void handle() { System.out.println("理財(cái):2000$"); } }
BankSaveMoneyHandler
package com.zrj.design.template.bank; /** * 存錢業(yè)務(wù) * * @author zrj * @since 2022/2/8 **/ public class BankSaveMoneyHandler extends BankBusinessHandler { /** * 辦理業(yè)務(wù) */ @Override public void handle() { System.out.println("存錢:1000$"); } }
2.3 銀行辦理業(yè)務(wù)函數(shù)式編程改造
BankBusinessHandlerCustomer
package com.zrj.design.template.customer; import cn.hutool.core.util.RandomUtil; import java.math.BigDecimal; import java.util.function.Consumer; /** * 模板設(shè)計(jì)模式的抽象類 * Java8函數(shù)式編程消費(fèi)者模式Customer實(shí)現(xiàn)模板設(shè)計(jì)模式 * * @author zrj * @since 2022/2/8 **/ public class BankBusinessHandlerCustomer { /** * 存錢 */ public void save(BigDecimal amount) { execute(a -> System.out.println("存錢:" + amount)); } /** * 理財(cái) */ public void draw(BigDecimal amount) { execute(a -> System.out.println("理財(cái):" + amount)); } /** * 模板方法,執(zhí)行器 */ public void execute(Consumer<BigDecimal> consumer) { getNumber(); consumer.accept(null); judge(); } /** * 取號(hào) */ private void getNumber() { System.out.println("取號(hào):" + RandomUtil.randomNumbers(8)); } /** * 評(píng)價(jià) */ private void judge() { System.out.println("評(píng)價(jià):五星好評(píng)!"); } }
BankBusinessHandlerCustomerTest
package com.zrj.design.template.customer; import java.math.BigDecimal; /** * @author zrj * @since 2022/2/8 **/ public class BankBusinessHandlerCustomerTest { public static void main(String[] args) { //構(gòu)建銀行業(yè)務(wù)處理對(duì)象 BankBusinessHandlerCustomer businessHandler = new BankBusinessHandlerCustomer(); //存錢業(yè)務(wù)處理 businessHandler.save(new BigDecimal("3000")); System.out.println("------------------------------"); //理財(cái)業(yè)務(wù)處理 businessHandler.draw(new BigDecimal("6000")); } }
到此這篇關(guān)于Java中的模板模式說明與實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java模板模式實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在MyBatisPlus中使用@TableField完成字段自動(dòng)填充的操作
這篇文章主要介紹了在MyBatisPlus中使用@TableField完成字段自動(dòng)填充的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02JavaWeb實(shí)現(xiàn)文件上傳與下載的方法
這篇文章主要介紹了JavaWeb實(shí)現(xiàn)文件上傳與下載的方法的相關(guān)資料,需要的朋友可以參考下2016-01-01SpringBoot-JPA刪除不成功,只執(zhí)行了查詢語句問題
這篇文章主要介紹了SpringBoot-JPA刪除不成功,只執(zhí)行了查詢語句問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12java連接mysql數(shù)據(jù)庫及測(cè)試是否連接成功的方法
這篇文章主要介紹了java連接mysql數(shù)據(jù)庫及測(cè)試是否連接成功的方法,結(jié)合完整實(shí)例形式分析了java基于jdbc連接mysql數(shù)據(jù)庫并返回連接狀態(tài)的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-09-09Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的長(zhǎng)輪詢的示例代碼
長(zhǎng)輪詢是與服務(wù)器保持即時(shí)通信的最簡(jiǎn)單的方式,它不使用任何特定的協(xié)議,例如 WebSocket ,所以也不依賴于瀏覽器版本等外部條件的兼容性。本文將用Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的長(zhǎng)輪詢,需要的可以參考一下2022-08-08三分鐘教你如何在IDEA中快速創(chuàng)建工程的方法
這篇文章主要介紹了三分鐘教你如何在IDEA中快速創(chuàng)建工程的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04Java中使用Jedis操作Redis的實(shí)現(xiàn)代碼
本篇文章主要介紹了Java中使用Jedis操作Redis的實(shí)現(xiàn)代碼。詳細(xì)的介紹了Redis的安裝和在java中的操作,具有一定的參考價(jià)值,有興趣的可以了解一下2017-05-05IDEA引MAVEN項(xiàng)目jar包依賴導(dǎo)入問題解決方法
這篇文章主要介紹了IDEA引MAVEN項(xiàng)目jar包依賴導(dǎo)入問題解決,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11Spring Boot中使用Spring-data-jpa實(shí)現(xiàn)數(shù)據(jù)庫增刪查改
本篇文章主要介紹了Spring Boot中使用Spring-data-jpa實(shí)現(xiàn)增刪查改,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2017-03-03