簡介
模板方法屬於行為型模式的一種.
實現層面上, 在抽象類別中定義了演算法或流程的骨架, 將其中易變的部分延遲到子類實現, 也就是允許它的子類實現其中的某些步驟.
模板方法適用於演算法不變, 但演算法中某些步驟有變化的情境, 例如Spring中JDBC事務操作,開啟串連-->開啟事務-->執行sql-->提交事務-->關閉串連, 每次操作均按照這個步驟進行, 變化的是執行的sql不一樣.
意圖
定義演算法架構,並將一些步驟的實現延遲到子類實現。
類圖
實現
一. 定義抽象類別, 並將演算法的骨架定義封裝到方法,注意方法用final修飾,防止有人繼承該類後對演算法做惡意修改, 不變的步驟可以實現
/** * 磨坊 */public abstract class MillTemplate { /** * 模板方法,定義步驟 */ public final void produce(){ //準備(可能是小麥,也可能是玉米) prepare(); //開機器 start(); //封裝 packaging(); //運輸(可能水路也可能火車) transport(); } //準備(可能是小麥,也可能是玉米) protected abstract void prepare(); private void start(){ System.out.println("啟動機器, 開始研磨..."); } private void packaging(){ System.out.println("封裝..."); } //運輸(可能水路也可能火車) protected abstract void transport(); }
二. 定義子類繼承抽象類別, 並實現抽象方法
/** * 玉米磨坊 */public class CoreMill extends MillTemplate { protected void prepare() { System.out.println("準備好玉米"); } protected void transport() { System.out.println("火車運輸"); }}
/** * 小麥磨坊 */public class WheatMill extends MillTemplate { protected void prepare() { System.out.println("準備好小麥"); } protected void transport() { System.out.println("船運"); }}
三. 調用
public class TemplateTest { public static void main(String[] args) { MillTemplate millTemplate = new WheatMill(); millTemplate.produce(); millTemplate = new CoreMill(); millTemplate.produce(); }}
四. 鉤子方法, 鉤子方法為模板的演算法提供了更大靈活性, 子類可以根據鉤子方法的結果控制一些步驟執行或不執行
我們在模板方法中增加鉤子方法
.../*** 模板方法,定義步驟*/public final void produce(){ //準備(可能是小麥,也可能是玉米) prepare(); //開機器 start(); //封裝 packaging(); //檢查的鉤子方法 if(needRecheck()){ recheck(); } //運輸(可能水路也可能火車) transport();}...//鉤子方法protected boolean needRecheck(){ return true;}//檢查private void recheck(){ System.out.println("檢查...");}...
子類重載鉤子方法已達到控制演算法某一步驟是否執行的目的
//WheatMill 中增加@Overrideprotected boolean needRecheck(){ return false;}
總結
優點: 1. 封裝了不變部分, 可變部分易於擴充;2. 便於代碼重用,便於維護
缺點: 每個不同的實現都需要一個子類, 導致類數量增加, 系統過於龐大