1. 程式人生 > >回撥方法、模板方法模式、鉤子(hook)區分

回撥方法、模板方法模式、鉤子(hook)區分

其實這三者之間沒什麼可區分的,因為他們是不同領域的概念。但是他們非常相似都是在抽象的定義了方法,然後子類實現它。他們都是java多型特性的實踐。

概念領域區分:

1.正確的說應該就是模板方法模式,模板方法模式提供模板方法,這個方法是一個模板演算法,或者說在方法的呼叫順序上固定了一個模板。
2.回撥方法,是固定一個方法外觀,java中通過介面實現。
3.鉤子方法,是一個抽象類提供空實現,子類進行選擇性重寫的方法。鉤子方法也出現在模板方法模式中。

區分

其實就是主要是模板方法模式和回撥模式的區分。簡單來說就是模板方法模式使用的是抽象類,既然要定義演算法邏輯,那麼就一定需要一個實現演算法的方法

模板方法模式與鉤子方法

詳見《head first設計模式》第8章——模板方法模式。
模板方法模式使用抽象類來定義方法呼叫的邏輯。子類繼承抽象類,從而獲取到了這個邏輯,然後提供某些具體方法實現。

abstract class AbstractClass{
    /*
    *模板方法,提供一種模板演算法或者說在方法的呼叫順序上固定了一個模板。
    */
    final void templateMenthod(){
        primitiveOperation1();
        primitiveOperation2();
        if(hookOperation()){
            concreteOperation();
        }
    }
    abstract
void primitiveOperation1(); abstract void primitiveOperation2(); void concreteOperation(){ //抽象類提供了某些實現 } boolean hookOperation(){ return true;//鉤子方法,子類可以實現這個方法,也可以不 } } class ConcreteClass1 extends AbstractClass{ @override void primitiveOperation1(){ System.out.println("con 1.1"
); } @override void primitiveOperation2(){ System.out.println("con 1.2"); } /* *重寫了鉤子方法,重置了判斷邏輯 */ @override boolean hookOperation(){ if(getUserInput().toLowerCase().startsWith("y")){ return true; }else{ return false; } } private String getUserInput(){ String answer = null; BufferedReader in = new BufferedReader (new InputStream(System.in)); try{ answer = in.readline; }catch (IOException e){ } if (answer == null){ return "no"; } return answer; } }

上面提供了一個子類實現了某些方法實現,最終使templateMenthod()這個方法能夠正常執行。

class ConcreteClass2 extends AbstractClass{
    @override
    void primitiveOperation1(){
        System.out.println("con 2.1");
    }
    @override
    void primitiveOperation2(){
        System.out.println("con 2.2");
    }
}
public class Test{
    public static void main(String[] args){
        ConcreteClass1 c1 = new ConcreteClass1();
        ConcreteClass2 c2 = new ConcreteClass2();
        c1.templateMenthod();
        c2.templateMenthod();
    }
}

AbstractClass定義了邏輯,子類提供了實現,這種設計模式解耦了演算法邏輯與具體實現,完成了演算法的程式碼複用。而鉤子方法給子類在一定程度上更改原先的邏輯,提供了一定的靈活性。

回撥方法

之前寫過一篇理解java中回撥機制的文章,具體可以看一看。
其實在C語言和js中都可以直接傳遞函式引用(要正確理解回撥可以先看一下js回撥函式的示例),而java中是沒有這一語法特性的 。那麼我們想要完成回撥就需要傳遞一個物件,然後在呼叫這個物件特定方法,通過介面我們約定方法的引數、返回值、方法名這些要素,使用的時候把具體的介面實現傳遞過去,就實現了方法的回撥。
可見回撥用到的是介面,而不是模板方法模式裡面的抽象類。

總結

回撥方法和模板方法使用了抽象方法,
回撥利用的介面,由於java中不具備傳遞函式指標這一語法特性,於是利用介面來實現方法回撥。它注重的是對方法的描述——方法名是什麼、方法引數有什麼、返回值如何。
模板方法模式利用抽象類,注重都是由父類來控制演算法邏輯,子類提供具體每個演算法步驟的實現。
鉤子方法其實就是普通的抽象類多型,它在模板方法模式中提供了改變原始邏輯的空間。