1. 程式人生 > >設計模式學習筆記十------模板方法模式

設計模式學習筆記十------模板方法模式

目錄

本文的結構如下:

  • 引言
  • 什麼是模板方法模式
  • 模式的結構
  • 程式碼示例
  • 優點和缺點
  • 適用環境
  • 模式應用

一、引言

讀初中的時候,家裡沒有電腦(話說現在老家也沒有電腦),父母又不讓玩手機,接觸比較多的電子產品就是MP4了,白天可以用來聽聽歌,晚上躲在被窩裡偷偷看小說。但那時MP4又不具備聯網下載功能,小說看完了,某個明星出新歌了,就愉快跑到網咖下載,順便也能玩會遊戲,看會視訊啥的,那時對網咖還是有很強的執念,基本上每次去網咖,都要去qq空間發一條狀態,很有趣。現在有電腦了,反而沒那種開心了,常常是半個月難得開一次機。

廢話不多說,轉入正題。

去網咖上網,可以簡單拆分一下,先是去網咖,然後開機,玩,最後關機離開。

有些是固定的,像開機,關機。但是有些地方卻不同,比如怎麼去網咖呢?每個人有不同的方式,同一個人不同的時刻也有不同的方式,可以跑步,可以走路,可以騎車,可以打的;到了網咖,玩什麼呢,也因人因時刻而定,看NBA,擼啊擼,碼程式碼都可以。

在軟體開發中,有時也會遇到類似的情況,某個方法的實現需要多個步驟(類似“去網咖上網”),其中有些步驟是固定的(類似“開機”和“關機”),而有些步驟並不固定,存在可變性(類似“去網咖和玩”)。為了提高程式碼的複用性和系統的靈活性,可以使用一種稱之為模板方法模式的設計模式來對這類情況進行設計,在模板方法模式中,將實現功能的每一個步驟所對應的方法稱為基本方法(例如“去網咖”、“開機”、“玩”和“關機”),而呼叫這些基本方法同時定義基本方法

的執行次序的方法稱為模板方法(例如“去網咖上網”)。在模板方法模式中,可以將相同的程式碼放在父類中,例如將模板方法“去網咖上網”以及基本方法“開機”和“關機”的實現放在父類中,而對於基本方法“去網咖”、“玩”,在父類中只做一個宣告,將其具體實現放在不同的子類中,在不同子類提供不同實現。通過使用模板方法模式,一方面提高了程式碼的複用性,另一方面還可以利用面向物件的多型性,在執行時選擇一種具體子類,提高系統的靈活性和可擴充套件性

二、什麼是模板方法模式

所以什麼是模板方法模式呢?

定義一個操作中演算法的框架,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。

模板方法模式是一種基於繼承的程式碼複用技術,它是一種類行為型模式

模板方法模式是結構最簡單的行為型設計模式,在其結構中只存在父類與子類之間的繼承關係。通過使用模板方法模式,可以將一些複雜流程的實現步驟封裝在一系列基本方法中,在抽象父類中提供一個稱之為模板方法的方法來定義這些基本方法的執行次序,而通過其子類來覆蓋某些步驟,從而使得相同的演算法框架可以有不同的執行結果。模板方法模式提供了一個模板方法來定義演算法框架,而某些具體步驟的實現可以在其子類中完成。

三、模式的結構

模板方法模式的結構很簡單,UML圖如下:

模板方法模式包含如下兩個角色:

  • AbstractClass(抽象類):在抽象類中定義了一系列基本操作(PrimitiveOperations),這些基本操作可以是具體的,也可以是抽象的,每一個基本操作對應演算法的一個步驟,在其子類中可以重定義或實現這些步驟。同時,在抽象類中實現了一個模板方法(Template Method),用於定義一個演算法的框架,模板方法不僅可以呼叫在抽象類中實現的基本方法,也可以呼叫在抽象類的子類中實現的基本方法,還可以呼叫其他物件中的方法。
  • ConcreteClass(具體子類):它是抽象類的子類,用於實現在父類中宣告的抽象基本操作以完成子類特定演算法的步驟,也可以覆蓋在父類中已經實現的具體基本操作。

3.1、模板方法

模板方法是定義在抽象類中的、把基本操作方法組合在一起形成一個總演算法或一個總行為的方法。

一般將模板方法定義為final,由子類不加以修改地完全繼承下來。模板方法是一個具體方法,它給出了一個頂層邏輯框架,而邏輯的組成步驟在抽象類中可以是具體方法,也可以是抽象方法。由於模板方法是具體方法,因此模板方法模式中的抽象層只能是抽象類,而不是介面。

3.2、基本方法

基本方法是實現演算法各個步驟的方法,是模板方法的組成部分。

基本方法又可以分為三種:

  • 抽象方法(Abstract Method)
  • 具體方法(Concrete Method)
  • 鉤子方法(Hook Method)

抽象方法:一個抽象方法由抽象類宣告、由其具體子類實現。具體方法:一個具體方法由一個抽象類或具體類宣告並實現,其子類可以進行覆蓋也可以直接繼承。鉤子方法:一個鉤子方法由一個抽象類或具體類宣告並實現,而其子類可能會加以擴充套件。通常在父類中給出的實現是一個空實現,並以該空實現作為方法的預設實現,當然鉤子方法也可以提供一個非空的預設實現。

具體方法和鉤子方法有些難以區分,我覺得其實也沒有必要區分那麼清楚,畢竟它們在類中都是一樣的,都不是抽象方法。只不過作用有點不一樣,具體方法是模板方法中一個預設已經實現的可以被子類複用的方法,更多的是複用,就像“去網咖上網”裡的“開機”和“關機”。而鉤子方法更多的是由子類選擇性複用,比如可以加兩個方法,“是否玩餓了?”、“吃點東西”,預設是不餓,返回false,可以用來做流程控制,子類根據需求覆蓋。

3.3、模板方法典型程式碼

抽象類:

/**
 * 
 * @author w1992wishes
 * @created @2017年11月15日-上午11:36:10
 *
 */
public abstract class AbstractClass {
    public final void templateMethod() {
        primitiveOperation1();
        if (primitiveOperation2()) {
            primitiveOperation3();
        }
    }

    /**
     * 抽象方法
     */
    protected abstract void primitiveOperation1();

    /**
     * 鉤子方法
     */
    public boolean primitiveOperation2() {
        return false;
    }

    /**
     * 具體方法
     */
    public void primitiveOperation3() {

    }
}

具體類:

/**
 * 
 * @author w1992wishes
 * @created @2017年11月15日-上午11:42:14
 *
 */
public class ConcreteClass extends AbstractClass {

    @Override
    public void primitiveOperation1() {
    }

    @Override
    public boolean primitiveOperation2() {
        return true;
    }

}

在模板方法模式中,由於面向物件的多型性,子類物件在執行時將覆蓋父類物件,子類中定義的方法也將覆蓋父類中定義的方法,因此程式在執行時,具體子類的基本方法將覆蓋父類中定義的基本方法,子類的鉤子方法也將覆蓋父類的鉤子方法,從而可以通過在子類中實現的鉤子方法對父類方法的執行進行約束,實現子類對父類行為的反向控制。

四、程式碼示例

這裡程式碼比較簡單,就略過了。

五、優點和缺點

5.1、優點

  • 在父類中形式化地定義一個演算法,而由它的子類來實現細節的處理,在子類實現詳細的處理演算法時並不會改變演算法中步驟的執行次序。
  • 模板方法模式是一種程式碼複用技術,它在類庫設計中尤為重要,它提取了類庫中的公共行為,將公共行為放在父類中,而通過其子類來實現不同的行為,它鼓勵我們恰當使用繼承來實現程式碼複用。
  • 可實現一種反向控制結構,通過子類覆蓋父類的鉤子方法來決定某一特定步驟是否需要執行。
  • 在模板方法模式中可以通過子類來覆蓋父類的基本方法,不同的子類可以提供基本方法的不同實現,更換和增加新的子類很方便,符合單一職責原則和開閉原則。

5.2、缺點

需要為每一個基本方法的不同實現提供一個子類,如果父類中可變的基本方法太多,將會導致類的個數增加,系統更加龐大,設計也更加抽象,此時,可結合橋接模式來進行設計。

六、適用環境

在以下情況下可以考慮使用模板方法模式:

  • 對一些複雜的演算法進行分割,將其演算法中固定不變的部分設計為模板方法和父類具體方法,而一些可以改變的細節由其子類來實現。即:一次性實現一個演算法的不變部分,並將可變的行為留給子類來實現。
  • 各子類中公共的行為應被提取出來並集中到一個公共父類中以避免程式碼重複。
  • 需要通過子類來決定父類演算法中某個步驟是否執行,實現子類對父類的反向控制。

七、模式應用

JAVA API中,集合框架提供了一個排序方法就是一個模板方法,其實核心部分是由compareTo方法實現的,有興趣的可以去看看原始碼。

--------------------- 本文來自 w1992wishes 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/w1992wishes/article/details/78539744?utm_source=copy