若是在項目開發中你常常看到一個類的某些方法和其餘類的方法功能相同,只有部分不一樣或者只有具體實現不一樣,亦或者是你看到某些方法在多個地方都存在,有不少重複代碼,這個時候你就能夠拿出模板設計模式了。java
模板方法(Template Method)模式的定義以下: 定義一個操做中的算法骨架,而將算法的一些步驟延遲到子類中,使得子類能夠不改變該算法結構的狀況下重定義該算法的某些特定步驟。它是一種類行爲型模式。面試
模板模式的主要優勢以下:算法
主要缺點以下:設計模式
模板模式涉及三個角色:框架
咱們的報銷系統分爲平常費用報銷和差旅費用報銷,報銷的流程是先根據報銷單上帶的費用計算出報銷金額,而後計算出報銷單中的補貼金額(如果差旅類型報銷才須要計算補貼,平常報銷不須要計算補貼),最後調用第三方接口建立流程。這個場景就適合用模板設計模式實現。ide
定義報銷流程的算法框架,算法框架使用final
修飾,對於必需要子類實現的方法用abstract
關鍵字修飾。ui
public abstract class AbstractReimburse { /** * 用做算法的模板 * 定義成final,以避免子模板改變算法的順序 */ final void calAndCreateFlow(){ BigDecimal totalMoney; BigDecimal changeMoney = calChangeMoney(); BigDecimal subsidyMoney = BigDecimal.ZERO; if(hasTravel()){ subsidyMoney = calSubsidyMoney(); } totalMoney = changeMoney.add(subsidyMoney); createWorkeFlow(totalMoney); } /** * 具體方法,子類判斷是否須要實現 * @param totalMoney 報銷總金額 */ protected void createWorkeFlow(BigDecimal totalMoney) { System.out.println("開始建立流程...,總報銷金額:"+totalMoney); //todo } /** * 鉤子方法,由子類決定是否實現,鉤子能夠做爲條件控制,影響抽象類中的算法流程 * 判斷是否須要計算補貼 */ boolean hasTravel() { return false; } /** * 抽象方法,須要子類去實現 * 返回須要報銷的費用金額 * @return 報銷的費用總金額 */ abstract BigDecimal calChangeMoney(); /** * 返回須要報銷的補貼金額 */ abstract BigDecimal calSubsidyMoney(); }
/** * 差旅類報銷實現邏輯 */ public class TravelReimburse extends AbstractReimburse{ @Override BigDecimal calChangeMoney() { System.out.println("差旅類報銷計算費用金額"); return new BigDecimal(1000); } @Override BigDecimal calSubsidyMoney() { System.out.println("差旅類報銷須要計算補貼"); return new BigDecimal(500); } @Override boolean hasTravel(){ return true; } }
/** * 平常類報銷實現邏輯 */ public class DailyReimburse extends AbstractReimburse{ @Override BigDecimal calChangeMoney() { System.out.println("平常類報銷計算費用金額"); return new BigDecimal(100); } @Override BigDecimal calSubsidyMoney() { return BigDecimal.ZERO; } }
public class ReimburseClient { public static void main(String[] args) { //差旅類報銷處理邏輯 TravelReimburse travelReimburse = new TravelReimburse(); travelReimburse.calAndCreateFlow(); System.out.println("==========================="); //平常類報銷處理邏輯 DailyReimburse dailyReimburse = new DailyReimburse(); dailyReimburse.calAndCreateFlow(); } }
模板模式應該是衆多設計模式中相對簡單的一種,可是它使用的頻率可一點也不低,在各類開源框架代碼中均可以看到它的身影,模板設計模式的應用場景主要有如下幾類:設計
tips 記得幾年前電話面試的時候,面試官問我有沒有用過模板設計模式,我回答說「啊,模板?你說的是freemarker嗎?巴拉巴拉一大堆」,而後電話嘟嘟嘟,留我一人在風中凌亂。3d
歡迎關注個人我的公衆號:JAVA日知錄