概念
模板方法模式在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。
模板方法模式類圖:
例子
大家可能還記得2000年趙本山跟宋丹丹小品的笑話吧,“把大象裝冰箱總共分三步,把冰箱門打開、把大象裝進去、把冰箱門關上”。那麼這個過程用代碼描述如下:
public class PutElephantInsideFridge{
public void openDoor(){
Sysrtem.out.println("打開冰箱門");
}
public void putElephant(){
Sysrtem.out.println("把大象裝進冰箱");
}
public void closeDoor(){
Sysrtem.out.println("關閉冰箱門");
}
public void put(){
this.openDoor();
this.putElephant();
this.closeDoor();
}
}
但是如果我想把獅子裝進冰箱,代碼該怎麼描述呢?顯然,除了第二步,其他都一樣。那麼面對第一、第二步冗餘的代碼可以將其抽象到父類中,第二步過程由子類去實現。put
方法用final
關鍵字修飾,避免子類破壞了算法流程。
public abstract class PutSomethingInsideFridge{
public void openDoor(){
Sysrtem.out.println("打開冰箱門");
}
public abstract void putSomething();
public void closeDoor(){
Sysrtem.out.println("關閉冰箱門");
}
public void put(){
this.openDoor();
this.putElephant();
this.closeDoor();
}
}
public class PutElephant extends PutSomethingInsideFridge{
@Override
public void putSomething(){
System.out.println("將大象裝進冰箱");
}
}
這就是一個簡單的模板方法模式,這樣改寫之後,以後再想把獅子、河馬放進冰箱也只需要多寫幾個類而不必重複整個算法流程。
鉤子函數
有用過React、Vue或者小程序開發經驗的小夥伴應該對coponentDidMount
、onLoad
等等生命週期函數不陌生,這些函數就是所謂的鉤子函數。而鉤子函數就是通過模板方法模式實現的。
還是以上面的例子爲例,假如我想在打開冰箱門之前再做點別的事,那麼就可以這樣做:
public abstract class PutSomethingInsideFridge{
public void openDoor(){
Sysrtem.out.println("打開冰箱門");
}
public abstract void putSomething();
public void closeDoor(){
Sysrtem.out.println("關閉冰箱門");
}
public void beforeOpenDoor(){
}
public void put(){
this.beforeOpenDoor();
this.openDoor();
this.putElephant();
this.closeDoor();
}
}
public class PutElephant extends PutSomethingInsideFridge{
@Override
public void putSomething(){
System.out.println("將大象裝進冰箱");
}
@Override
public void beforeOpenDoor(){
System.out.println("打開冰箱門之前");
}
}
總結
模板方法模式就是將子類中不變的部分抽象到父類,可變的部分由子類去實現。
優點
模板方法模式是將子類中不變的部分抽象到父類,可變的部分由子類去實現。
缺點
每新增一個不同的實現都需要增加一個子類,可能導致類數量變多,增加系統複雜性