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

目錄

本文的結構如下:

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

一、引言

讀初中的時候,家裏沒有電腦(話說現在老家也沒有電腦),父母又不讓玩手機,接觸比較多的電子產品就是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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章