【設計模式】模板模式

 引子

  這是一個很簡單的模式,卻被很是普遍的使用。算法

  之因此簡單是由於在這個模式中僅僅使用到了繼承關係。設計模式

  繼承關係因爲自身的缺陷,被專家們扣上了「罪惡」的帽子。框架

  「使用委派關係代替繼承關係」,ide

  「儘可能使用接口實現而不是抽象類繼承」等等專家警告,讓咱們你們對繼承「刮目相看」。測試

  其實,繼承仍是有不少自身的優勢所在。只是被你們濫用的彷佛缺點更加明顯了。編碼

  合理的利用繼承關係,仍是能對你的系統設計起到很好的做用的。spa

  而模板方法模式就是其中的一個使用範例。設計

定義與結構

  模板方法(Template Method)模式:code

  定義一個操做中的算法的骨架,而將一些步驟延遲到子類中。使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定步驟。blog

  這裏的算法的結構,能夠理解爲你根據需求設計出來的業務流程。

  特定的步驟就是指那些可能在內容上存在變數的環節。

  能夠看出來,模板方法模式也是爲了巧妙解決變化對系統帶來的影響而設計的。

  使用模板方法使系統擴展性加強,最小化了變化對系統的影響。

模板模式結構

  1. 抽象類(Abstract Class):定義了一到多個的抽象方法,以供具體的子類來實現它們;並且還要實現一個模板方法,來定義一個算法的骨架。該模板方法不只調用前面的抽象方法,也能夠調用其餘的操做,只要能完成自身的使命。
  2. 具體類(Concrete Class):實現父類中的抽象方法以完成算法中與特定子類相關的步驟。

結構圖

  直接把《設計模式》上的圖拿過來用下

 

  

舉例

  JUnit 中的 TestCase 以及它的子類就是一個模板方法模式的例子。

  在 TestCase 這個抽象類中將整個測試的流程設置好了,好比

  1. 先執行 Setup 方法初始化測試前提,
  2. 在運行測試方法,
  3. 而後再 TearDown 來取消測試設置。

  可是你將在 Setup、TearDown 裏面做些什麼呢?鬼才知道呢!!

  所以,而這些步驟的具體實現都延遲到子類中去,也就是你實現的測試類中。

  來看下相關的源代碼吧。

  這是 TestCase 中,執行測試的模板方法。

public void runBare() throws Throwable {
    setUp();
    try {
          runTest();
    }
    finally {
          tearDown();
    }
}
View Code

  你能夠看到,裏面正像前面定義中所說的那樣,它制定了「算法」的框架——先執行 setUp 方法來作下初始化,而後執行測試方法,最後執行 tearDown 釋放你獲得的資源。

protected void setUp() throws Exception {
}
protected void tearDown() throws Exception {
}
View Code

  這就是上面使用的兩個方法。

  與定義中不一樣的是,這兩個方法並無被實現爲抽象方法,而是兩個空的無爲方法(被稱爲鉤子方法)。

  這是由於在測試中,咱們並非必需要讓測試程序使用這兩個方法來初始化和釋放資源的。

  若是是抽象方法,則子類們必須給它一個實現,無論用到用不到。這顯然是不合理的。

  使用鉤子方法,則你在須要的時候,能夠在子類中重寫這些方法。

適用狀況

  根據上面對定義的分析,以及例子的說明,能夠看出模板方法適用於如下狀況

  1. 一次性實現一個算法的不變的部分,並將可變的行爲留給子類來實現。
  2. 各子類中公共的行爲應被提取出來並集中到一個公共父類中以免代碼重複。其實這能夠說是一種好的編碼習慣了。
  3. 控制子類擴展。模板方法只在特定點調用操做,這樣就只容許在這些點進行擴展。

  好比上面 runBare()方法就只在 runTest 前面適用 setUp 方法。

  若是你不肯子類來修改你的模板方法定義的框架,你能夠採用兩種方式來作:

  1. 一是在 API 中不體現出你的模板方法;
  2. 或者將你的模板方法置爲 final 就能夠了。

  能夠看出(優勢):

  1. 使用模板方法模式能夠將代碼的公共行爲提取出來,達到複用的目的。
  2. 並且,在模板方法模式中,是由父類的模板方法來控制子類中的具體實現。這樣你在實現子類的時候,根本不須要對業務流程有太多的瞭解。

 

  @成鵬致遠

(blogs:lcw.cnblogs.com

(emailwwwlllll@126.com)

(qq552158509)

相關文章
相關標籤/搜索