設計模式之模板方法模式實戰解析

来源:https://www.cnblogs.com/nesger/archive/2019/09/02/11444583.html
-Advertisement-
Play Games

本文微信公眾號「AndroidTraveler」首發。 背景 最近在看《設計模式之禪》,為了能夠更加深入的理解設計模式,達到學以致用。 這邊記錄一下自己的一些感受和看法,並結合具體代碼實戰來進行說明。 模板方法模式 但凡和設計模式掛上鉤,我們總是會覺得「高不可攀」。 然而實際上,設計模式是基於大量實 ...


本文微信公眾號「AndroidTraveler」首發。

背景

最近在看《設計模式之禪》,為了能夠更加深入的理解設計模式,達到學以致用。
這邊記錄一下自己的一些感受和看法,並結合具體代碼實戰來進行說明。

模板方法模式

但凡和設計模式掛上鉤,我們總是會覺得「高不可攀」。
然而實際上,設計模式是基於大量實際代碼的經驗總結,它來自於實際的代碼。
與其說「高不可攀」,其實它反而是比較「接地氣」。
而模板方法模式相信你看完本篇文章之後,會發現,原來這就是模板方法模式,然後就去看你之前的代碼了。

小例子初識模板方法模式

理解設計模式最好的方法就是通過項目開發中的實際場景來說明。

大家做 Android 開發的時候寫 Activity 應該都會看到下麵類似代碼吧?

private void getIntents() {
    // 從 Intent 獲取傳遞過來的一些參數,設置到屬性中
}

private void findViewById() {
    // 通過 findViewById 來初始化各個組件
}

private void setViews() {
    // 給組件設置監聽或者初始狀態
}

假設我每個界面都這樣寫,那麼重覆代碼太多了,很沒必要。
雖然每個方法具體的邏輯不一樣,但是都有這些操作。

這個時候我們第一個想法就是繼承,抽取出一個 BaseActivity。
然後將這些通用代碼都放到了 BaseActivity 裡面,子類再來覆寫就可以了。

但是還有一個問題,那就是,我每次都需要寫下麵代碼:

getIntents();
findViewById();
setViews();

尤其是通用代碼多的時候,有時候手誤可能導致某些界面這三個方法調用順序還不一樣。
那怎麼辦呢?我們可以抽取出一個方法,這個方法代表了這三個方法統一的調用順序,這樣就不怕手誤寫錯了。
而這個方法就是我們的模板方法

public abstract class BaseActivity extends Activity {
    /**
     * 從 Intent 獲取傳遞過來的一些參數,設置到屬性中
     */
    protected abstract void getIntents();

    /**
     * 通過 findViewById 來初始化各個組件
     */
    protected abstract void findViewById();

    /**
     * 給組件設置監聽或者初始狀態
     */
    protected abstract void setViews();

    /**
     * 模板方法
     */
    final public void init() {
        getIntents();
        findViewById();
        setViews();
    }
}

這樣我後面的 Activity 都可以繼承這個 BaseActivity,然後只需要調用 init 方法即可。
至於不同的 Activity 的邏輯我再在三個方法裡面各自實現即可。

鉤子方法

一聽到這個詞,是不是覺得有點「高大上」,似乎很 NB?
然而,聽完我後面的講述,你內心估計

我們上面的方法裡面,並不是所有的 Activity 都有其他 Activity 傳遞數據過來的,因此 getIntents 這個方法不一定所有子類都要調用。
這個時候我們可以提供一個鉤子方法,改動部分代碼如下:

/**
 * 模板方法
 */
final public void init() {
    if (isGetIntents()) {
        getIntents();
    }
    findViewById();
    setViews();
}

/**
 * 鉤子方法,是否需要設置數據,預設為 true
 * @return
 */
protected boolean isGetIntents() {
    return true;
}

可以看到,通過鉤子方法,當我們預設需要獲取數據時,什麼都不用改動,如果我們不需要獲取數據,只需要覆寫我們的鉤子方法 isGetIntents 並返回 false 即可。

好了,有了初步的印象之後,接下來就正式的加深瞭解吧。

定義

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
定義一個操作中的演算法的框架,而將一些步驟延遲到子類中。使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。

簡單的說就是父類定義了一個模板方法,在這個模板方法裡面有一些特定的步驟。具體的步驟實現留給子類去處理。

父類的模板方法保持了各個子類的共性,模板方法裡面的步驟使得每個子類都有自己的個性。

通用代碼實現

父類:

public abstract class AbstractPatternClass {
    /**
     * 基本方法,模板方法裡面調用
     */
    protected abstract void firstModule();
    /**
     * 基本方法,模板方法裡面調用
     */
    protected abstract void secondModule();

    /**
     * 模板方法,多個基本方法組合
     */
    final public void templateMethod() {
        firstModule();
        secondModule();
    }
}

具體子類:

public class ConcreteClass extends AbstractPatternClass {
    @Override
    protected void firstModule() {
        // TODO 子類實現自己的邏輯
    }

    @Override
    protected void secondModule() {
        // TODO 子類實現自己的邏輯
    }
}

場景使用類:

public class PatternTest {
    public static void main(String[] args) {
        AbstractPatternClass abstractPatternClass = new ConcreteClass();
        // 調用模板方法
        abstractPatternClass.templateMethod();
    }
}

鉤子方法我們上面已經說過了,相信聰明的你知道如何使用,這裡就不再贅述了。

註意點

父類中的基本方法儘量設計為 protected 類型,符合迪米特法則。
父類中的模板方法一般設置為 final,不允許子類覆寫。這樣的目的一個是為了避免子類惡意操作,一個是為了模板的共性。

應用

當你在寫代碼經常用到複製和粘貼快捷鍵時,你就要考慮是不是可以進行抽取。
當你修改一個地方的時候,發現其他地方也要連帶修改,也需要考慮一下。
多個子類有公共方法,並且邏輯基本相同。
複雜的一些演算法之類的,可以讓子類通過基本方法傳遞一些參數,核心邏輯放在模板方法裡面。
重構項目的時候,也可以考慮一下把相同代碼抽取到父類,通過鉤子方法定製化模板。

結語

最後一點就是註意不要濫用設計模式,不要為了設計而設計

參考資料
設計模式之禪(第2版)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • const portfinder = require('portfinder'); const port = await portfinder.getPortPromise(); 兩行代碼 埠搜索範圍 預設情況下,portfinder將開始搜索8000並掃描,直到達到最大埠號(65535) 源碼 ...
  • JS一個重要功能就是操作DOM, 改變頁面顯示。 目錄: 1、基本概念 2、節點類型 3、節點關係 4、節點操作 基本概念 DOM全稱為Document Object Model ,即文檔對象模型,是針對HTML和XML的一個API, 描繪了一個層次化的節點樹,可以添加、移除和修改頁面的某一部分。 ...
  • 雲計算和移動計算令已經很脆弱的身份及訪問管理(IAM)基礎設施更加搖搖欲墜。問題的日益嚴重推動單點登錄、多因數身份驗證、IAM集中化等領域出現相應變革。 " " 幾年前,CISO們就感受到了雲計算和移動計算時代維持安全控制的艱難。隨著雲計算和移動計算的興起,身份和數據安全已經變成了新的安全邊界,企業 ...
  • 雲已經改變了我們工作的方式,且在不遠的將來,這一動作仍將持續。在雲為員工提供各種便利,為公司企業帶來成本節約、價值提升、工序縮減等收益的同時,新的挑戰也隨之而來。Gartner預測,到2020年, 90% 的企業都將管理 由雲和內部解決方案組成的混合IT基礎設施 ,這無疑會使得安全挑戰和困難變得更加 ...
  • JS數組的方法眾多,平時在使用的時候,容易忘記某些不常用的數組方法,而且時長把兩個差不多的方法搞混。而且ES6在ES5的基礎上又新增了一些方法,為了方便記憶,就寫篇博客方便記憶,沒事的時候拿出來看看。 數組方法: 1.push() 用法:在數組的最後一位添加數據,同時返回插入後的數組長度。 var ...
  • RxJS 的操作符(operators)是最有用的,儘管 Observable 是最基本的。操作符最基本的部分(pieces)就是以申明的方式允許複雜的非同步代碼組合簡化。 什麼是操作符? 操作符是函數。這裡有兩種操作符: 管道操作符(Pipeable Operators)是可以通過使用 管道傳輸到 ...
  • jQuery對象是一個類數組對象,它保存的是對應的DOM的引用,我們可以直接用[]獲取某個索引內的DOM節點,也可以用get方法獲取某個索引內的DOM節點,還可以用toArray()方法把jQuery對象一次性轉換成一個數組,例如: 將DOM對象轉換為jQuery對象就更方便了,直接放到jQuery ...
  • 希望它可以像鋼鐵俠中的 Jarvis 一樣幫我們解決資源的管控問題。 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...