Java設計模式之模板方法模式

Java設計模式之模板方法模式

1.什麼是模板方法模式(Template Method) 爲算法的執行定義了一個統一的框架,其中的某些具體實現方法需要他在子類中去完成,每個子類所做的事情可能都不一樣,而子類可以在不改變這個框架的同時去完成該算法的某個具體步驟,這就是我們所說的模板模式。

生活中的模板:

銀行辦理業務,1、進門取號 2、填寫單據 3、等待叫號 4、窗口辦理,對於這四個規則,所有
來辦理業務的人都需要遵循這四種規則,但是在四個規則中規則2填寫單據去是需要顧客填寫的,
因爲銀行他並不知道顧客具體要辦理什麼樣的業務,所以,他只能讓顧客自己去填寫這樣的單據,
這樣銀行就是爲顧客定義了一個模板。

2.如何實現模板方法模式

1.首先需要一個抽象基類,爲所有子類提供一個算法框架  
2.定義一個模板方法,封裝所有子類共同遵循的算法框架  
3.將對應的步奏寫入模板方法中,將所有共同方法聲明爲私有的或者final方法,爲了隱藏實現細節  
4.將所有並不知道具體實現什麼的方法設置爲抽象方法,爲了讓他的子類去實現具體細節  
5.所有子類的具體實現    

細節:鉤子方法實現:加入一個判斷條件,詢問用戶是否需要執行該操作,提供一個默認或空的實現,讓子類去選擇是否掛鉤,
模板方法模式的實現要素:
準備一個抽象類,將部分邏輯以具體方法的形式實現,然後聲明一些抽象方法交由子類實現剩餘邏輯,用鉤子方法給予子類更大的靈活性,最後將方法彙總構成一個不可改變的模板方法。

3.模板方法模式的特點

優點:封裝性好,、複用性好、屏蔽細節、便於維護

缺點:繼承的侷限性

4.模板方法模式在項目中的應用

1.算法或操作遵循相似的邏輯  

2.重構時,把相同的代碼抽取到父類中  

3.重要、複雜的算法,核心算法設計爲模板算法  

下面就通過寫一個銀行辦理業務的模板模式:

首先是一個抽象基類:

BankOption.java

    public abstract  class BankOption {

    protected String name;
    public BankOption(String name){
        this.name = name;
    }
    public void templete(){
        //1.辦理業務
        business();
        //2.填寫單據
        writeBills();
        //3.等待呼叫
        callWait();
        //4.窗口辦理
        windowDeal();
    }

    /**
     * 辦理業務
     */
    private   void business(){
        System.out.println(name + "辦理業務");
    }

    /**
     * 填寫單據,具體填寫說明單據,讓用戶自己選擇
     */
    protected abstract void writeBills();

    /**
     * 等待呼叫
     */
    private  void callWait(){
        System.out.println(name + "等待呼叫...");
        //模擬顧客等待5秒鐘
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //5秒後等待結束,可以辦理業務了
        System.out.println("呼叫" + name + "到窗口辦理業務");
    }

    /**
     * 窗口辦理
     */
    private   void windowDeal(){
        System.out.println(name + "窗口辦理");
        System.out.println("窗口辦理中...");
        //模擬在窗口辦理業務時3秒鐘
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + "辦理業務完成");
    }

}

Customer1.java

    public class Customer1 extends BankOption{
    public Customer1(String name){
        super(name);
    }
    @Override
    protected void writeBills() {
        System.out.println(name + "填寫匯款單據");
    }
}

Customer2.java

    public class Customer2 extends BankOption{
    public Customer2(String name){
        super(name);
    }
    @Override
    protected void writeBills() {
        System.out.println(name + "填寫存款單據");
    }
}

Customer3.java

    public class Customer3 extends BankOption{
    public Customer3(String name){
        super(name);
    }
    @Override
    protected void writeBills() {
        System.out.println(name + "填寫辦理銀行卡業務");
    }
}

Main.java測試類:

public class Main {
    public static void main(String[] args) {
        BankOption c1 = new Customer1("顧客1");
        BankOption c2 = new Customer2("顧客2");
        BankOption c3 = new Customer3("顧客3");
        c1.templete();
        System.out.println("\n*************************");
        c2.templete();
        System.out.println("*************************");
        c3.templete();

        }
    }

運行結果:
顧客1辦理業務
顧客1填寫匯款單據
顧客1等待呼叫…
呼叫顧客1到窗口辦理業務
顧客1窗口辦理
窗口辦理中…
顧客1辦理業務完成

***************

顧客2辦理業務
顧客2填寫存款單據
顧客2等待呼叫…
呼叫顧客2到窗口辦理業務
顧客2窗口辦理
窗口辦理中…
顧客2辦理業務完成

***************

顧客3辦理業務
顧客3填寫辦理銀行卡業務
顧客3等待呼叫…
呼叫顧客3到窗口辦理業務
顧客3窗口辦理
窗口辦理中…
顧客3辦理業務完成

上就是一個簡單的銀行辦理業務的模板方法模式,我們把所以規定了的步奏,1、3、4都寫在基類中,這樣很好的隱藏了實現細節,顧客只需要填寫對應的單據就行了,那麼我們可以通過上面的例子再改進下,來理解下上面提到的細節:鉤子方法,爲什麼使用鉤子方法呢?上面我們每個用戶都模擬了等待呼叫功能,有時候如果另外一個窗口已經是空閒的,就可以直接叫用戶去辦理業務了,這個時候我們就可以使用鉤子方法了,當鉤子方法鉤上的時候,也就是在本程序中表示,你可以不用等待呼叫,直接去窗口辦理業務了,如果沒有鉤上,就表示你要繼續等待,這裏就模擬一下,1、3不等待,2等待。通過一下代碼比較一下。

BankOption.java中加入一個鉤子方法即可

public void templete(){
        //1.辦理業務
        business();
        //2.填寫單據
        writeBills();
        //3.等待呼叫
        if(isWait())
            callWait();
        else
            System.out.println("不需要等待");
        //4.窗口辦理
        windowDeal();
    }
    //通過加入這個方法去判斷是否需要等待,當然,這裏有點不符合實際,
    //因爲這裏是用戶去實現是否等待,一般來說我們是銀行來控制是否顧客等待,不過只要大家理解鉤子方法是什麼意思就可以了
    protected abstract boolean isWait();

然後每個用戶去添加實現鉤子方法即可:

Customer1.java

    @Override
    protected boolean isWait() {
        //false表示不需要等待,直接辦理窗口
        return false;
    }

Customer2.java

     @Override
    protected boolean isWait() {
        //表示需要等待
        return true;
    }

Customer3.java

    @Override
    protected boolean isWait() {
        //不需要等待
        return false;
    }

運行結果:

顧客1辦理業務
顧客1填寫匯款單據
不需要等待
顧客1窗口辦理
窗口辦理中…
顧客1辦理業務完成

***************
顧客2辦理業務
顧客2填寫存款單據
顧客2等待呼叫…
呼叫顧客2到窗口辦理業務
顧客2窗口辦理
窗口辦理中…
顧客2辦理業務完成

***************
顧客3辦理業務
顧客3填寫辦理銀行卡業務
不需要等待
顧客3窗口辦理
窗口辦理中…
顧客3辦理業務完成

模板方法模式就介紹到這裏,在我們的實際開發應用過程中,模板方法模式應用非常廣泛,所以這種設計模式大家一定得掌握。

發佈了58 篇原創文章 · 獲贊 19 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章