動機:在軟件構建過程中,對於某一項任務,他常常有穩定的整體操作結構,但各個子步驟卻有很多改變的需求,或者由於固有的原因(比如框架與應用之間的關係)而無法和任務的整體結構同時實現;如何在確定穩定操作結構的前提下,來靈活應對各種子步驟的變化或者晚期實現需求?
意圖:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。TemplateMethod是的子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
適用性:
1、一次性實現一個算法的不變的部分,並將可變的行爲留給子類來實現。
2、各子類中公共的行爲應被提取出來並集中到一個公共父類中以避免代碼重複。這是O p d y k e 和J o h n s o n 所描述過的“重分解以一般化”的一個很好的例子[ O J 9 3 ]。首先識別現有代碼中的不同之處,並且將不同之處分離爲新的操作。最後,用一個調用這些新的操作的模板方法來替換這些不同的代碼。
3、控制子類擴展。模板方法只在特定點調用“h o o k ”操作,這樣就只允許在這些點進行擴展。
UML圖解:
示例:假設要開發一款汽車測試程序,而對於測試什麼類型和什麼牌子的汽車,都是是未知的。應用模板方法來設計,我們就可以先把汽車測試程序測試涉及的方法列舉出來,對於某些測試方法具體實現留給後來汽車廠商去實現,代碼如下
汽車測試軟件框架部分:
1 //汽車測試軟件框架的開發組——先開發 2 namespace TemplateMethod 3 { 4 public abstract class Vehicle 5 { 6 protected abstract void Startup(); 7 protected abstract void Run(); 8 protected abstract void Turn(); 9 protected abstract void Stop(); 10 11 public void Test() 12 { 13 Startup();//晚綁定,留給應用程序開發人員實現,擴展點 14 //測試數據記錄... 15 16 Run();//晚綁定,留給應用程序開發人員實現,擴展點 17 //測試數據記錄... 18 19 Turn();//晚綁定,留給應用程序開發人員實現,擴展點 20 //測試數據記錄... 21 22 Stop();//晚綁定,留給應用程序開發人員實現,擴展點 23 //測試數據記錄... 24 } 25 } 26 27 public class VehicleTestFramework 28 { 29 public static void DoTest(Vehicle vehicle) 30 { 31 //... 32 vehicle.Test(); 33 //... 34 } 35 } 36 }
具體汽車廠商後來實現部分:
1 //具體汽車廠商汽車測試程序程序開發組——晚開發 2 namespace TemplateMethod 3 { 4 public class DaZhongCar:Vehicle 5 { 6 protected override void Startup() 7 { 8 //... 9 } 10 11 protected override void Run() 12 { 13 //... 14 } 15 16 protected override void Turn() 17 { 18 //... 19 } 20 21 protected override void Stop() 22 { 23 //... 24 } 25 } 26 }