定義
定義一個(gè)操作中的算法的框架,而將一些步驟延遲到子類中,使得子類可以可以不改變一個(gè)算法結(jié)構(gòu)即可重新定義該算法的某些特定步驟。
也就是流程封裝。把某個(gè)固定的流程封裝到一個(gè) final函數(shù)中,并且讓子類能夠定制這個(gè)流程中的某些或者所有步驟,其要求父類提取共用的代碼,提升代碼的復(fù)用率,帶來更好的可擴(kuò)展性。
使用場景
多個(gè)子類有公有的方法,并且邏輯基本相同時(shí)
重要,復(fù)雜的算法,可以把核心算法設(shè)計(jì)為模版方法,周邊的相關(guān)細(xì)節(jié)功能則由各個(gè)子類實(shí)現(xiàn)
重構(gòu)時(shí),模版方法模式是一個(gè)經(jīng)常使用的模式,把相同的代碼抽取到父類中,然后通關(guān)重寫某些子函數(shù)約束其行為。
Android中的AsyncTask,Android應(yīng)用的生命周期(比如onCreate, onStart,OnResume)這些都是典型的模版方法模式
通俗一點(diǎn)的說就是,主要的過程已經(jīng)確定好了,你需要處理的主要是中間某個(gè)過程的某個(gè)細(xì)節(jié)。
UML圖
- AbsTemplate:抽象類,定義了一套算法框架
- ConcreteImplA: 具體實(shí)現(xiàn)類A
- ConcreteImplB: 具體實(shí)現(xiàn)類B
優(yōu)點(diǎn)
- 封裝不變部分,擴(kuò)展可變部分
- 提取公共部分代碼,便于維護(hù)
缺點(diǎn)
- 模版方法會(huì)帶來代碼閱讀的難度,讓用戶覺得難以理解
例子
小白的電腦,軍用電腦,程序員電腦的啟動(dòng)是不一樣的。但是基本流程是不變的,比如
- 開啟電源
- 硬件檢查
- 載入操作系統(tǒng)
- 登錄系統(tǒng)
這幾個(gè)流程,程序員的電腦也許第4步要輸密碼才能進(jìn)入系統(tǒng),而軍用電腦第2步也許要檢查硬件防火墻,第四步還要檢查指紋啥的這些,按照基本流程,然后新的類隨意定制。這就是模版方法模式。
/**
* 抽象的Computer,相當(dāng)于UML圖中的AbsTemplete
* Created by Niwa on 2017/8/15.
*/
public class AbstractComputer {
protected void powerOn() {
System.out.println("開啟電源");
}
protected void checkHardWare() {
System.out.println("硬件檢查");
}
protected void loadOs() {
System.out.println("載入操作系統(tǒng)");
}
protected void login() {
System.out.println("小白的系統(tǒng)不驗(yàn)證,直接登錄系統(tǒng)");
}
/**
* 啟動(dòng)計(jì)算機(jī)的方法,步驟固定為開啟電源,硬件檢查,加載操作系統(tǒng),登錄系統(tǒng)
* <p>final方法,無法被重寫了</p>
*/
public final void startUp() {
System.out.println("-----------關(guān)機(jī)START---------");
powerOn();
checkHardWare();
loadOs();
login();
System.out.println("-------------關(guān)機(jī)END---------------");
}
}
/**
* 程序員的計(jì)算機(jī),相當(dāng)于UML圖中的ConcreteImplA
* Created by Niwa on 2017/8/15.
*/
public class CoderComputer extends AbstractComputer {
@Override
protected void login() {
System.out.println("coder只需要進(jìn)行用戶和密碼驗(yàn)證就可以了");
}
}
/**
* 軍用的的計(jì)算機(jī),相當(dāng)于UML圖中的ConcreteImplB
* Created by Niwa on 2017/8/15.
*/
public class MilitaryComputer extends AbstractComputer {
@Override
protected void checkHardWare() {
super.checkHardWare();
System.out.println("檢查硬件防火墻");
}
@Override
protected void login() {
System.out.println("科學(xué)家進(jìn)行指紋識(shí)別等復(fù)雜驗(yàn)證");
}
}
/** 測試類
* Created by Niwa on 2017/8/15.
*/
public class Test {
public static void main(String[] args){
//普通電腦
AbstractComputer computer = new AbstractComputer();
computer.startUp();
//軍用電腦
computer = new MilitaryComputer();
computer.startUp();
}
}
結(jié)果:
-----------關(guān)機(jī)START---------
開啟電源
硬件檢查
載入操作系統(tǒng)
小白的系統(tǒng)不驗(yàn)證,直接登錄系統(tǒng)
-------------關(guān)機(jī)END---------------
-----------關(guān)機(jī)START---------
開啟電源
硬件檢查
檢查硬件防火墻
載入操作系統(tǒng)
科學(xué)家進(jìn)行指紋識(shí)別等復(fù)雜驗(yàn)證
-------------關(guān)機(jī)END---------------
參考:
《Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)讀書》
各大佬博客
源代碼:DesignPattern
end