模板方法模式--鉤子方法

前言

  說到模(mú)板,很多人都接觸過,C++和Java都有諸如List和Stack這樣的模板類。但是說到模板方法,很多人可能說不太清楚,或者雖然在學習工作中接觸到了,但是不知道其實它是一種模板方法。

  按照設計模式一書的說法,模板方法模式是將一個算法的一部分邏輯下移給子類去定義和實現。


敘述

  根據上面的說法,一般我們使用抽象類而非接口來進行模板方法的實現。爲什麼呢?因爲是一個算法的一部分邏輯,這說明其中有一部分是父類已經定義並實現的,子類掌握的是部分步驟的重寫權限。
  一般來說,我們可以將一個模板方法父類進行如下的定義:

public abstract class AbstractParent{
    //骨架方法
    public void skeleton(){
        concreteMethod();
        hookMethod();
        abstractMethod();
    }

    //具體方法
    public void concreteMethod(){
        System.out.println("Here comes the concrete method.");
    }

    //鉤子方法
    public void hookMethod(){}

    //抽象方法
    public abstract void abstractMethod();
}

骨架方法

  主要定義了整個方法需要實現的業務操作的骨架。其中調用不同方法的順序因人而異,而且這個方法也可以做成一個抽象方法要求子類自行定義邏輯流程。

  其中調用了具體方法、鉤子方法、抽象方法,也可以根據實際情況增加其他邏輯或條件等。


具體方法

  一個骨架中,有可能有一些邏輯是確定不變的,這個時候可以直接在父類中定義完全的已實現的方法,無需子類再進行覆蓋。


抽象方法

  一個普通的抽象方法,放在這個地方其實也是增強了父類提供給子類的靈活性。


鉤子方法

  大家可以看到,這個方法雖然說不是abstract的,但是實現中沒有任何語句。這個時候其實我們是想讓子類去覆蓋(Override)這個方法。


何謂鉤子(hook)?

不是由該方法的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。

如果某個子類需要在ConcreteMethod方法後,在AbstractMethod方法前進行某些操作,就可以覆蓋這個鉤子方法,實現自己的邏輯即可,並不需要修改父類或其調用方。
鉤子就是在整體流程的設計中,故意留下的供子類靈活變更的鑰匙。

鉤子是一種被聲明在抽象類中的方法,但鉤子只有空的或者默認方法實現。鉤子的存在,可以讓子類有能力對算法的不同點進行掛鉤。要不要掛鉤由子類自行決定。

當在模板方法中某一些步驟是可選的時候,也就是該步驟不一定要執行,可以由子類來決定是否要執行,則此時就需要用上鉤子。鉤子是一種被聲明在抽象類中的方法,但一般來說它只是空的或者具有默認值,子類可以實現覆蓋該鉤子,來設置算法步驟的某一步驟是否要執行。鉤子可以讓子類實現算法中可選的部分,讓子類能夠有機會對模板方法中某些一即將發生的步驟做出反應。


鉤子方法實現方式

方式一

最簡單的鉤子方法就是空方法,代碼如下:

public virtual void Display() { }

當然也可以在鉤子方法中定義一個默認的實現,如果子類不覆蓋鉤子方法,則執行父類的默認實現代碼。

方式二

另一種鉤子方法可以實現對其他方法進行約束,這種鉤子方法通常返回一個 bool 類型,即返回 true 或 false,用來判斷是否執行某一個基本方法,下面通過一個實例來說明這種鉤子方法的使用。

代碼如下:
抽象父類

public abstract class AbstractClass {

    public abstract boolean isOpen();

    public final void operating() {
        if(isOpen()) {
            System.out.println("鉤子方法開啓");
        }else {
            System.out.println("鉤子方法關閉");
        }
    }
}

實現類

public class AchieveClass extends AbstractClass {

  //鉤子方法能掛在到operating能干預到operating業務邏輯
    @Override
    public boolean isOpen() {
        return true;
    }

    public static void main(String[] args) {
        AchieveClass ac = new AchieveClass();
        ac.operating();
    }

}

只要重寫isOpen就能干預父類方法的業務流程。相當於將isOpen掛載在了父類的operating()中。


小結

鉤子顧名思義就是用來掛東西的。那麼要掛東西必須有個被掛的東西,要不就是鐵環、要不就是牆的邊沿。所以要能掛住東西必須要有個被勾住的鐵環,要一個鉤子。那麼在java中也是同樣的原理,你首先需要一個被掛在的東西,一個掛載的東西。

感謝您的閱讀~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章