模板方法模式——《設(shè)計(jì)模式之禪》
例子
悍馬模型抽象接口
// 抽象是所有子類(lèi)的共性封裝
public abstract class HummerModel{
/**
* run();
* 這是一個(gè)匯總的方法
*/
final abstract void run(){
this.start();
this.engineBoom();
if(this.isAlarm()){
this.alarm();
}
this.stop();
}
//車(chē)輛發(fā)動(dòng)
protected abstract void start();
//車(chē)輛停止
protected abstract void stop();
//車(chē)輛鳴叫
protected abstract void alarm();
//車(chē)輛加速
protected abstract void engineBoom();
//hook函數(shù),約束是否鳴笛
protected boolean isAlarm(){
return true;
}
}
public class HummerH1Model extends HummerModel {
private boolean alarmFlag = true;
protected void alarm(){
System.out.println("悍馬H1鳴笛");
}
protected void start(){
System.out.println("悍馬H1發(fā)動(dòng)");
}
protected void stop(){
System.out.println("悍馬H1停止");
}
protected void engineBoom(){
System.out.println("引擎聲音");
}
//hook函數(shù),重新實(shí)現(xiàn)可以實(shí)現(xiàn)自定義是否鳴笛
protected boolean isAlarm(){
return this.alarmFlag;
}
// 由客戶(hù)實(shí)現(xiàn)是否鳴笛
public void setAlarm(boolean isAlarm){
this.alarmFlag = isAlarm;
}
}
public class HummerH2Model extends HummerModel {
protected void alarm(){
System.out.println("悍馬H2鳴笛");
}
protected void start(){
System.out.println("悍馬H2發(fā)動(dòng)");
}
protected void stop(){
System.out.println("悍馬H2停止");
}
protected void engineBoom(){
System.out.println("引擎聲音");
}
//hook函數(shù)晴埂,重新實(shí)現(xiàn)可以實(shí)現(xiàn)自定義是否鳴笛
protected boolean isAlarm(){
return false;
}
}
public class Client{
public static void main(String[] args) throws IOException {
HummerModel h1 = new HummerH1Model();
h1.run();
HummerModel h2 = new HummerH2Model();
h2.run();
}
}
模板方法模式的定義
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm' s structure.
定義一個(gè)操作中的算法的框架躏鱼,而將一些步驟延遲到子類(lèi)中剩燥。使得子類(lèi)可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某特定步驟
模板方法模式
模板方法模式的特點(diǎn)
- 模板方法模式確實(shí)非常簡(jiǎn)單揭保,僅僅使用了java的繼承機(jī)制埃叭,其中睁搭,AbstractClass叫做抽象模板
- 基本方法:基本方法也叫做基本操作,是由子類(lèi)實(shí)現(xiàn)的方法吱型,并且在模板方法中被調(diào)用
- 模板方法:可以有一個(gè)或幾個(gè)逸贾,一般是一個(gè)具體方法,也就是一個(gè)框架津滞,實(shí)現(xiàn)對(duì)基本方法的調(diào)度铝侵,完成固定的邏輯
- 為了安全起見(jiàn),模板方法一般加修飾符:final防止被惡意修改
- 在類(lèi)圖中有一個(gè)角色:具體模板触徐。ConcreteClass1和ConcreteClass2屬于具體模板咪鲜,實(shí)現(xiàn)父類(lèi)所定義的一個(gè)或多個(gè)抽象方法。也就是父類(lèi)定義的基本方法在子類(lèi)中得以實(shí)現(xiàn)
抽象模板類(lèi)
public abstract class AbstractClass{
// 基本方法
protected abstract void doSomething();
// 基本方法
protected abstract void doAnything();
// 模板方法
public void templateMethod(){
/**
* 調(diào)用基本方法撞鹉,完成相關(guān)的邏輯
*/
}
}
具體模板類(lèi)
public class ConcreteClass1 extends AbstractClass{
// 實(shí)現(xiàn)基本方法
protected void doAnything(){
// code to do something
}
protected void doSomething(){
// code to do something()
}
}
public class ConcreteClass2 extends AbstractClass{
// 實(shí)現(xiàn)基本方法
protected void doAnything(){
// code to do something
}
protected void doSomething(){
// code to do something()
}
}
場(chǎng)景類(lèi)
public class Client{
public static void main(String[] args) {
AbstractClass class1 = new ConcreteClass1();
AbstractClass class2 = new ConcreteClass2();
// 調(diào)用模板方法
class1.templateMethod();
class2.templateMethod();
}
}
注意事項(xiàng)
- 抽象模板中的基本方法盡量設(shè)計(jì)為protected類(lèi)型疟丙,符合迪米特法則颖侄。不需要暴露的屬性或方法盡量不要設(shè)置為protected屬性
- 實(shí)現(xiàn)類(lèi)若非必要,盡量不要擴(kuò)大父類(lèi)的訪(fǎng)問(wèn)權(quán)限
模板方法模式的優(yōu)缺點(diǎn)
模板方法模式的優(yōu)點(diǎn)
封裝不變部分享郊,擴(kuò)展可變部分
提取公共部分代碼览祖,便于維護(hù)
-
行為由父類(lèi)控制,子類(lèi)實(shí)現(xiàn)炊琉。
基本方法是由子類(lèi)實(shí)現(xiàn)的展蒂,因此子類(lèi)可以通過(guò)擴(kuò)展的方法增加相應(yīng)的功能,符合開(kāi)閉原則
模板方法模式的缺點(diǎn)
- 模板方法模式抽象類(lèi)定義了部分抽象方法温自,由子類(lèi)實(shí)現(xiàn)玄货,子類(lèi)執(zhí)行的結(jié)果對(duì)父類(lèi)產(chǎn)生了影響皇钞,會(huì)帶來(lái)代碼閱讀的難度
模板方法模式的適用場(chǎng)景
- 多個(gè)子類(lèi)有公有的方法悼泌,并且邏輯基本相同時(shí)
- 重要、復(fù)雜的算法夹界,可以把核心算法設(shè)計(jì)為模板方法馆里,周邊的相關(guān)細(xì)節(jié)功能則由各個(gè)子類(lèi)實(shí)現(xiàn)
- 重構(gòu)時(shí),模板方法模式是一個(gè)經(jīng)常使用的模式可柿,把相同的代碼抽取到父類(lèi)中鸠踪,然后通過(guò)hook函數(shù)約束行為
擴(kuò)展:父類(lèi)調(diào)用子類(lèi)的方法
- 把父類(lèi)傳遞到子類(lèi)的有參構(gòu)造中,然后調(diào)用
- 使用反射的方式調(diào)用
- 父類(lèi)調(diào)用子類(lèi)的靜態(tài)方法
- 模板方法模式:修改子類(lèi)的方法复斥,影響父類(lèi)的行為