軟體設計模式系列之二十四——模板方法模式

来源:https://www.cnblogs.com/coodream2009/archive/2023/10/05/17742018.html
-Advertisement-
Play Games

本文記錄了穩定性摸排過程中的一些思考和沉澱。 前言 在之前寫了篇文章《上線十年,81萬行Java代碼的老系統如何重構》,在文章後有同學留言問“這麼複雜的改動,質量是如何應對的”,是一個特別好的問題,當時只是從現有的一些監控、測試、卡口手段上進行了回答。但在回答過程當中就在思考一個問題,交接過來的老代 ...


在軟體設計領域,設計模式是一組被反覆使用、多次實踐驗證的經典問題解決方案。其中,模板方法模式是一種行為型設計模式,用於定義一個演算法的骨架,將演算法中的某些步驟延遲到子類中實現,從而使子類可以重新定義演算法的某些特定步驟,同時保持演算法的整體結構不變。本文將深入探討模板方法模式,包括其定義、舉例、結構、實現步驟、代碼實現、典型應用場景、優缺點、類似模式以及一個小結。

1 模式的定義

模板方法模式是一種行為型設計模式,它定義了一個演算法的骨架,將演算法的具體步驟延遲到子類中實現。這意味著,模板方法模式允許多個子類共用相同的演算法框架,但可以在子類中實現各自特定的步驟,從而實現了代碼的復用和擴展。通常,模板方法由一個抽象類定義,其中包含了演算法的骨架,以及一些抽象方法,用於由子類來實現。

2 舉例說明

在日常生活中,有許多例子符合模板方法模式的設計,這些例子都展示了一種在不同場景中重覆使用相同的步驟或演算法骨架的情況。以下是幾個大家熟知的例子:

烹飪食物:烹飪是一個典型的模板方法模式示例。無論是製作披薩、漢堡、還是義大利面,都需要執行一系列共同的步驟,如準備食材、烹飪、裝盤等。不同的食物有不同的特定步驟,可以在子類中實現。

咖啡店的飲料製作:就像前文提到的咖啡和茶的例子一樣,咖啡店製作不同飲料也遵循相似的模板,包括燒水、沖泡、倒入杯子和加入調味品等步驟。

電子商務購物流程:線上購物網站通常具有相似的購物流程,包括瀏覽商品、將商品添加到購物車、填寫配送信息、選擇支付方式、確認訂單等步驟。不同電子商務網站可以在這些步驟的執行順序和細節上進行定製。

這些例子都展示了在日常生活中廣泛存在的模板方法模式的應用,其中共用的步驟或演算法骨架可以在不同的情境中重覆使用,而特定的細節可以在子類或具體實例中定製。這種設計方法有助於提高效率、減少重覆工作,並確保一致性。

3 結構

模板方法模式包含以下主要組成部分:

抽象類(Abstract Class):定義演算法的骨架,包含一個或多個抽象方法,用於由子類實現。通常,抽象類還包含模板方法,該方法定義了演算法的步驟順序。

具體子類(Concrete Subclass):實現抽象類中的抽象方法,從而提供了演算法的具體實現。

4 實現步驟

下麵是使用模板方法模式的一般實現步驟:

創建一個抽象類,定義演算法的骨架,併在其中聲明抽象方法。

在抽象類中實現模板方法,該方法包含演算法的步驟順序,其中調用了抽象方法。

創建具體子類,繼承自抽象類,並實現抽象方法以提供具體的演算法實現。

在客戶端代碼中,使用具體子類來調用模板方法以執行演算法。

5 代碼實現

以下是一個使用Java語言實現的製作咖啡和茶的示例代碼:

// 抽象類:飲料製備模板
abstract class Beverage {
    // 模板方法,製備飲料
    final void prepareBeverage() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    // 抽象方法:燒水
    abstract void boilWater();

    // 抽象方法:沖泡
    abstract void brew();

    // 抽象方法:倒入杯子
    abstract void pourInCup();

    // 抽象方法:加入調味品
    abstract void addCondiments();
}

// 具體子類:咖啡
class Coffee extends Beverage {
    @Override
    void boilWater() {
        System.out.println("燒水");
    }

    @Override
    void brew() {
        System.out.println("沖泡咖啡");
    }

    @Override
    void pourInCup() {
        System.out.println("倒入杯子");
    }

    @Override
    void addCondiments() {
        System.out.println("加入糖和牛奶");
    }
}

// 具體子類:茶
class Tea extends Beverage {
    @Override
    void boilWater() {
        System.out.println("燒水");
    }

    @Override
    void brew() {
        System.out.println("沖泡茶葉");
    }

    @Override
    void pourInCup() {
        System.out.println("倒入杯子");
    }

    @Override
    void addCondiments() {
        System.out.println("加入檸檬");
    }
}

public class TemplateMethodPatternExample {
    public static void main(String[] args) {
        Beverage coffee = new Coffee();
        coffee.prepareBeverage();

        Beverage tea = new Tea();
        tea.prepareBeverage();
    }
}

6 典型應用場景

模板方法模式在實際軟體開發中有許多應用場景,其中一些典型的包括:

框架設計:在框架中,模板方法模式用於定義框架的核心演算法,而具體的功能由子類實現。例如,Java中的Servlet就是使用了模板方法模式。

庫設計:在庫中,模板方法模式用於定義通用的演算法,以滿足不同的客戶需求。客戶可以通過繼承庫中的類並實現抽象方法來自定義功能。

游戲開發:在游戲開發中,模板方法模式可用於定義游戲中的角色行為或關卡設計,其中不同的角色或關卡可以通過繼承來實現特定的行為。

7 優缺點

優點:

代碼復用:模板方法模式提供了一種代碼復用的方式,使得多個子類可以共用演算法的核心結構,減少了重覆代碼的數量。

擴展性:模板方法模式允許子類擴展或修改演算法的特定步驟,而不需要改變演算法的整體結構。

高層控制:模板方法模式將演算法的控制權交給了抽象類,使得高層模塊可以更方便地控制演算法的執行。

缺點:

過度抽象:如果不合理地設計抽象類和抽象方法,可能會導致過度抽象,使得代碼難以理解和維護。

限制子類:模板方法模式要求子類必須按照模板方法的順序執行演算法步驟,這可能會限制子類的靈活性。

8 類似模式

與模板方法模式類似的模式包括以下幾種:

策略模式(Strategy Pattern):策略模式也允許在運行時選擇演算法,但與模板方法模式不同,它將演算法封裝成獨立的對象,使得客戶可以在運行時切換不同的演算法實現。模板方法模式通過繼承來實現演算法的變化,而策略模式通過組合和委托來實現。兩者都涉及到將演算法進行抽象,但模板方法模式更適用於定義演算法的骨架,而策略模式更適用於在不同演算法之間進行動態切換。

工廠方法模式(Factory Method Pattern):工廠方法模式用於創建對象,它定義一個創建對象的介面,但讓子類決定實例化哪個類。雖然工廠方法模式通常不涉及演算法的執行順序,但它也可以看作是一種創建對象的模板,具有一定的相似性。兩者都涉及創建對象,但工廠方法模式關註對象的創建,而模板方法模式關註定義演算法的骨架。

命令模式(Command Pattern):命令模式將請求封裝成對象,使得可以在不同的上下文中執行請求。雖然命令模式主要關註將請求和執行解耦,但在一些情況下,可以使用模板方法模式來定義具體的命令執行流程。兩者都涉及定義執行流程,但命令模式主要用於將請求和執行解耦,而模板方法模式主要用於定義演算法的骨架。

雖然這些模式有一些相似之處,但它們的主要關註點和使用方式略有不同。模板方法模式的主要目的是定義演算法的骨架,允許子類定製特定的步驟,而其他模式更側重於其他領域,如創建對象、封裝請求等。因此,在選擇使用哪種模式時,需要根據具體的需求和問題來決定哪種模式更適合。

9 小結

模板方法模式是一種強大的設計模式,它允許我們定義演算法的骨架並延遲特定步驟的實現到子類中。通過這種方式,我們可以實現代碼的復用和擴展,同時保持演算法的整體結構不變。在實際應用中,模板方法模式常用於框架和庫的設計,以及需要定義多個具有相似結構的演算法的場景。但要謹慎使用,避免過度抽象和限制子類的問題。在正確的情況下,模板方法模式可以提高代碼的可維護性和靈活性,使軟體更易於擴展和維護。


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

-Advertisement-
Play Games
更多相關文章
  • 眾所周知,在Cortex-M內核中,系統節拍由Systick時鐘提供,當配置好系統滴答時鐘後,每次時鐘中斷就會觸發中斷處理函數 xPortSysTickHandler(), void xPortSysTickHandler( void ) { /* The SysTick runs at the l ...
  • 搭建msf 官方有提供一鍵安裝腳本,如下: curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate ...
  • MySQL 是世界上最流行的開源關係型資料庫管理系統之一,而其中的存儲引擎則是其關鍵組成部分之一。InnoDB 存儲引擎在 MySQL 中扮演了重要角色,提供了許多高級功能和性能優化,適用於各種應用程式和工作負載。本文將深入介紹 InnoDB 存儲引擎的各個方面,以幫助您更好地理解它的特性和優勢。 ...
  • 1. 為什麼要拆分資料庫? 單體項目在構建之初,資料庫的負載和數據量都不大,所以不需要對資料庫做拆分,小型財務系統、文書系統、ERP系統、OA系統,用一個MySQL資料庫實例基本就夠用了。 就像《淘寶技術這十年》裡面說到的,電商業務的數據量增長飛快,所以最開始的PHP+MySQL的架構已經不能滿足實 ...
  • 【Flutter】如何優美地實現一個懸浮NavigationBar 最近寫代碼的時候遇到了一個如下的需求: 整體來說,底部的條是一個浮動的懸浮窗,有如下的三個按鈕: 點擊左邊的要進入“主頁” 點擊中間的按鈕要進行頁面跳轉,能夠進入“創作頁” 點擊右邊的按鈕切換到“個人中心”頁 使用Overlay來實 ...
  • 經過 Adobe 工程師多年來的努力,並與 Chrome 等瀏覽器供應商密切合作,通過 WebAssembly + Emscripten、Web Components + Lit、Service Workers + Workbox 和新的 Web API 的支持,終於在近期推出了 Web 版 Pho ...
  • 主要增加對容器創建 MySQL、Mongo 時對 數據文件,日誌,配置,網路,時區,埠映射,密碼 的配置,更貼合生產環境的實際使用 ...
  • 軟體設計原則 GRASP 通用職責分配軟體模式 來自 Craig Larman 的軟體設計書《UML 和模式應用》,Larman 在書中提出軟體設計的關鍵任務是職責分配,並提煉總結出 9 種 (5 種核心 +4 種擴展) 軟體職責分配模式,這些模式是比 GoF 設計模式更抽象的元模式。 信息專家 ( ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...