Design Patterns——Template Method入門到情景實戰

Template Method

什麼是Template Method

Template Method的設計思想

簡單的說,就是爲了不在多個子類實現某個算法的過程當中,應用程序開發人員寫錯了算法過程,而致使產生了錯誤的結果。咱們讓類庫開發人員本身寫一個固定的算法骨架(因而此模式只能適應於算法骨架基本肯定的應用場景!)。讓一部分全部類都公用的算法、步驟,在類庫中實現,而後讓不一樣的應用程序開發人員書寫適用於當前場景的部分步驟,而後調用父類的骨架方法,實現算法!java

在Template Method設計模式中有哪些類型的方法

第一:交給類庫實現的,應用程序開發人員不能修改的固定的方法

好比下面的實戰1的銀行業務辦理程序,取號、業務結束給出評價,這兩個步驟是不一樣的應用程序不須要管理的,因而設置爲final的(在Java程序設計中是final,若是是c++程序設計則把函數實現寫成const便可!)。這些程序每每是一些和任何應用程序開發者無關的代碼,設置成final避免應用程序開發者無心中修改,致使了算法的結果錯誤!c++

第二:交給類庫實現的,可是應用程序開發人員可根據實際狀況,考慮修改或者不修改的

好比下面的實戰2的數據分析程序,有些應用程序(子類)的應用場景下的數據,須要被加工再能被分析!可是有些數據是能夠直接拿來分析,好比:Excel的數據每每能夠在download後直接拿來處理,可是一些柱狀圖制類的數據須要二次加工後再處理!因此咱們能夠設置一個《鉤子函數》的hook方法,這種方法通常是返回布爾值的(boolean/bool)。若是大多數狀況是須要處理的,咱們就給這個hook方法默認返回一個false,避免有些應用程序開發者忘記處理而進入數據分析的流程!若是當前的數據是不須要二次加工的,則拓展的子類重寫該方法,返回true便可!算法

第三:交給應用程序開發者實現的,在抽象類中無論的抽象方法

抽象方法在Java中,以關鍵字abstract來體現,有abstract標註的方法的類,稱之爲抽象類。若是是在c++中,則是設置純虛函數,有純虛函數的類是抽象類。這個方法咱們不能拿來實現,只須要在父類中定義,而後編譯器會強制要去應用程序的開發者去根據本身的實際狀況來實現抽象類。起到在運行期多態的效果!編程

使用 Template Method的好處

讓算法固定,達到一種父類去調用子類的效果,符合《開閉原則》!
又利用繼承與多態,達到算法骨架的代碼複用的效果!設計模式

模板方法相關實戰1:銀行業務辦理程序

設計分析:

在銀行辦理業務這個算法流程(骨架)中,有一下幾個步驟:
① 取號
② 辦理業務
③ 業務結束,給出本次業務的評價markdown

其中有一些過程(方法)是靜態的,就是取號、業務結束,這兩個步驟。可是辦理業務的過程是動態的,不一樣的用戶角色,想辦理不一樣的業務!因此咱們只能把這個動態的過程(方法)抽象化,而固定不變的算法骨架。讓不一樣的須要辦理業務的角色類去繼承這個抽象類,而後在子類中重寫須要辦理的業務,在重寫結束後,再在調用的主類中去調用整個算法骨架process()。根據多態性,會根據子類的不一樣、實現的辦理業務的程序的不一樣,在相同的算法骨架中獲得不一樣的結果!ide

個人抽象父類:BankTranscation

/** * 這個抽象類做爲模板方法的父類,完成銀行業務 * @author 不會編程的小良 * @version 1.0 * */
abstract class BaseBankTranscation {

    static int ServerId = 1;

    public void takeNumber(){
        System.out.println("排隊取號ing……");
    }

    /** * 這個抽象函數負責由子類根據具體業務完成重寫 * @author 不會編程的小良 * @version 1.0 * */
    public abstract void transcation();

    public void evalue(){
        System.out.println("第 " + ServerId + " 次服務結束,完成評分……");
    }

    public final void process(){
        System.out.println("開始第 " + ServerId + " 次服務!");
        takeNumber();
        transcation();
        evalue();
        ServerId++;
    }

}

不一樣業務辦理的子類

/** * 這個子類負責重寫父類BaseBankTranscation的方法transcation(),完成取款業務 * @author 不會編程的小良 * @version 1.0 * */
class Deposite extends BaseBankTranscation {

    @Override
    public void transcation() {
        System.out.println("我要取款……");
    }
}

/** * 這個子類負責重寫父類BaseBankTranscation的方法transcation(),完成存款業務 * @author 不會編程的小良 * @version 1.0 * */
class Withdraw extends BaseBankTranscation {

    @Override
    public void transcation() {
        System.out.println("我要存款……");
    }
}

/** * 這個子類負責重寫父類BaseBankTranscation的方法transcation(),完成轉帳業務 * @author 不會編程的小良 * @version 1.0 * */
class Transfer extends BaseBankTranscation {

    @Override
    public void transcation() {
        System.out.println("我要轉帳……");
    }
}

主類調用各個子類的process方法,完成業務辦理

/** * 這個主類負責完成各類銀行業務的辦理過程 * @author 不會編程的小良 * @version 1.0 * */
public class TemplateMethod {

    public static void main(String[] args){

        int n = 3;
        BaseBankTranscation[] tran = new BaseBankTranscation[n];
        for(int i = 0;i < n;++i){
            switch (i % 3){
                case 0:
                    tran[i] = new Deposite();
                    break;
                case 1:
                    tran[i] = new Withdraw();
                    break;
                case 2:
                    tran[i] = new Transfer();
                    break;
                default:
                    break;
            }
        }
        for(BaseBankTranscation item : tran) {
            item.process();
        }

    }
}

執行的結果是:

在這裏插入圖片描述

模板方法相關實戰2:數據處理與分析案例

設計分析:

這個數據處理與分析分紅幾個步驟:函數

① 數據獲取(應用程序完成的抽象方法)
② 數據轉換成可處理的模式 (hook方法)
③ 數據分析(應用程序完成的抽象方法)
④ 數據分析的結果展現(hook方法)測試

父類BaseDataAnalysis的實現

abstract class BaseDataAnalysis {

    abstract void getData();

    void connvertData(){
        System.out.println("默認的數據轉換方法……");
    }

    final void analysisData(){
        System.out.println("完成數據分析工做……");
    }

    void displayData(){
        System.out.println("默認的輸出方式展現……");
    }

    boolean isValid(){
        return true;
    }

    void process(){
        getData();
        if(isValid()){
            connvertData();
        }
        analysisData();
        displayData();
    }

}

拓展出來的子類SubClass實現

class SubClass extends BaseDataAnalysis {

    @Override
    void getData(){
        System.out.println("從JSON文件中獲取數據……");
    }

    @Override
    void displayData(){
        System.out.println("以餅狀圖展現的方法展現……");
    }
}

主類的測試方法執行

public class TemplateMethod {
    public static void main(String[] args){
        BaseDataAnalysis sub = new SubClass();
        sub.process();
    }
}

執行的結果是:

在這裏插入圖片描述

思考與練習

問題描述:

某銀行軟件的利息計算流程以下:atom

① 系統根據帳戶查詢用戶信息

② 根據用戶信息來判斷用戶類型

③ 不一樣類型的用戶使用不一樣的利息計算方式(如活期、按期)

④ 顯示利息

個人解決方案——抽象銀行利息類:

abstract class BankInterest {

    boolean isValidUser(String username, String password){
        if("jiangzhengliang".equals(username) && "123456".equals(password)) {
            System.out.println("帳戶:" + username);
            System.out.println("密碼:" + password);
            return true;
        }
        else {
            return false;
        }
    }

    abstract void getAccountMethod();

    final void display(){
        System.out.println("顯示利息……");
    }

    void process(String name, String psswd){
        if(isValidUser(name, psswd)){
            getAccountMethod();
            display();
        }
    }

}

個人解決方案——拓展的活期、按期利息子類

class CurrentAccount extends BankInterest {

    @Override
    void getAccountMethod() {
        System.out.println("我是活期貸款……");
    }
}

class SavingAccount extends BankInterest {

    @Override
    void getAccountMethod() {
        System.out.println("我是按期貸款……");
    }
}

個人解決方案——測試主類

public class TemplateMethod {
    public static void main(String[] args){
        BankInterest bank1 = new CurrentAccount();
        bank1.process("jiangzhengliang", "123456");

        BankInterest bank2 = new SavingAccount();
        bank2.process("jiangzhengliang", "123456");
    }
}

測試的結果:

在這裏插入圖片描述

相關文章
相關標籤/搜索