模板方法模式是類的行爲模式,準備一個抽象類,將部分邏輯以具體方法以及具體構造子的形式實現,而後聲明一些抽象方法來迫使子類實現剩餘邏輯。不一樣的子類能夠以不一樣的方式實現這些抽象方法,從而對剩餘的邏輯有不一樣的實現。這就是模板方法的用意。
模板方法模式是基於繼承的代碼複用技術,模版方法模式的結構和用法也是面向對象設計的核心。
它涉及
兩個角色:
1.抽象模版(Abstract Template)角色有以下責任
定義一個或多個抽象操做,以便讓子類實現。這些抽象操做叫作基本操做,它們是一個頂級邏輯的組成步驟
定義並實現了一個模板方法。這個模板方法通常是一個具體方法,它給出了一個頂級邏輯的骨架,而邏輯的組成步驟在相應的抽象操做中,推遲到子類實現。頂級邏輯也有可能調用一些具體方法
2.具體模版(Concrete Template)角色有以下責任:
實現父類所定義的一個或多個抽象方法,它們是一個頂級邏輯的組成步驟
每個抽象模板角色均可以有任意多個具體模板角色與之對應,而每個具體模板角色均可以給出這些抽象方法(也就是頂級邏輯的組成步驟)的不一樣實現,從而使得頂級邏輯的實現各不相同。
模板方法鼓勵恰當地使用繼承,此模式能夠用來改寫一些擁有相同功能的相關的類,將可複用的通常性的行爲代碼移到基類裏面,而把特殊化的行爲代碼移到子類裏面。
示例代碼:
1 public class TemplateMethodTest {
2 public static void main(String[] args) {
3 AbstractClass ac = new ConcreteClass();
4 ac.TemplateMethod();
5 }
6 }
7 //抽象模板類
8 abstract class AbstractClass{
9 //模版方法的聲明和實現
10 public void TemplateMethod(){
11 //調用基本方法(由子類實現)
12 doOperation1();
13 doOperation2();
14 doOperation3();
15 }
16 //基本方法聲明(由子類實現)
17 protected abstract void doOperation1();
18 protected abstract void doOperation2();
19 protected abstract void doOperation3();
20 }
21
22 //具體模版類
23 class ConcreteClass extends AbstractClass{
24
25 @Override
26 protected void doOperation1() {
27 System.out.println("Do one");
28 }
29
30 @Override
31 protected void doOperation2() {
32 System.out.println("Do two");
33 }
34
35 @Override
36 protected void doOperation3() {
37 System.out.println("Do three");
38 }
39
40 }
模板方法中的方法:
1.模版方法:一個模板方法是定義在抽象類中的,把基本操做方法組合在一塊兒造成一個總算法或一個總行爲的方法。這個模板方法通常會在抽象類中定義,並由子類不加以修改地徹底繼承下來。
一個抽象類能夠有任意多個模版方法,而不限於一個。每個模版方法均可以調用 任意多個具體方法。
2.基本方法:又分爲三種
2.1抽象方法:一個抽象方法由抽象類聲明,由具體子類實現
2.2具體方法:一個具體方法由抽象類聲明並實現,而子類並不實現或置換。有些具體方法能夠起到工廠方法的做用,這樣的具體方法又叫作工廠方法。
2.3.鉤子方法:一個鉤子方法由抽象類聲明並實現,而子類會加以擴展。一般抽象類給出的實現是一個空實現,做爲方法的默認實現。鉤子方法的名字應當以do開始,這是熟悉設計模式的Java程序設計師的標準作法。在HttpServlet裏面,基本方法也聽從這一命名規則
模版方法與重構及設計:
在對一個繼承的等級結構作重構時,一個應當聽從的原則是將行爲儘可能移動到結構的頂端,而將狀態儘可能移動到結構的低端。
1.應當根據行爲而不是狀態定義一個類。也就是說,一個類的實現首先創建在行爲的基礎上,而不是創建在狀態的基礎之上
2.在實現行爲時,是用抽象狀態而不是具體狀態。若是一個行爲涉及到對象的狀態時,使用間接的引用而不是直接的引用。就是,應當使用取值方法而不是直接引用屬性
3.給操做劃分層次,一個類的行爲應當放到一個小組核心方法裏面,這些方法能夠很方便地在子類中加以置換
4.將狀態屬性的確認推遲到子類中,不要在抽象類中過早聲明屬性變量,應將它們儘可能推遲到子類中去聲明。在抽象超類中,若是須要狀態屬性的話,能夠調用抽象的取值方法,而將抽象的取值方法的實現放到具體子類中。
若是能聽從這樣的原則,那麼就能夠在等級結構中將接口與實現分隔開來,將抽象與具體分割開來,從而保證代碼能夠最大限度地被複用。