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