【設計模式深度剖析】【1】【行為型】【模板方法模式】| 以烹飪過程為例加深理解

👈?上一篇:結構型設計模式對比

文章目錄

  • 模板方法模式
  • 定義
    • 英文原話
    • 直譯
    • 如何理解呢?
  • 2個角色
    • 類圖
    • 代碼示例
  • 應用
    • 優點
    • 缺點
    • 使用場景
  • 示例解析:以烹飪過程為例
    • 類圖
    • 代碼示例

模板方法模式

模板方法模式(Template Method Pattern)是一種行為型設計模式,它通過一個抽象類定義了一個操作的算法骨架,而將一些步驟延遲到子類中實現。

簡而言之,模板方法模式就像是一個烹飪食譜,規定了基本的烹飪流程(算法骨架),但允許廚師根據具體食材(子類)調整某些步驟(如烹飪時間、溫度等),從而制作出不同風味的菜肴

定義

英文原話

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.

直譯

定義一個操作中的算法框架,進而推遲一些步驟的執行,將其延遲到子類中。模板方法使得子類在不改變算法的結構的情況下,可以改變算法的某些特定步驟。

如何理解呢?

模板方法模式從字面上理解,可以拆分為“模板”和“方法”兩個部分。

  1. 模板:指的是一種固定的框架或結構,它定義了某個過程或操作的基本流程或步驟。在模板方法模式中,這個“模板”通常由抽象類中的模板方法提供,該方法定義了一個算法的框架,即算法執行的大致步驟和順序。
  2. 方法:指的是具體的操作或步驟。在模板方法模式中,這些“方法”通常包括抽象方法(由子類實現)和具體方法(在抽象類中實現)。抽象方法定義了算法中需要子類實現的部分,而具體方法則包含了算法中通用的、不需要子類改變的部分。

我們可以以一個簡單的烹飪過程為例。假設我們有一個基本的烹飪流程,其中包含了預熱烤箱、烹飪食物和關閉烤箱的步驟。但不同的食物需要不同的烹飪時間和溫度,這部分就是可以定制的部分。

假設我們想要烤一個蛋糕和一個披薩。兩者都需要預熱烤箱,但烹飪時間和溫度不同,烹飪完成后都需要關閉烤箱。這里,預熱烤箱和關閉烤箱就是模板方法中固定的部分,而烹飪食物則是需要根據不同食物來定制的部分。(見下文示例解析)

2個角色

模板方法模式(Template Method Pattern)中的角色通常包括:

  1. 抽象類(Abstract Class):這個角色定義了一個或多個抽象操作,以便讓子類實現。這些抽象操作是基本操作,還需要定義一個或幾個模板方法,這些模板方法一般是具體的方法,定義了一個算法的框架。
  2. 具體子類(Concrete Subclasses):這是抽象模板角色的子類,它們實現抽象模板角色中的抽象方法,以完成算法中與特定子類相關的步驟。

通過使用模板方法模式,開發者可以在不改變算法結構的情況下,通過子類來重定義算法的某些特定步驟,從而實現算法的靈活性和可復用性。

類圖

在這里插入圖片描述

代碼示例

下面是一個Java示例,展示了模板方法模式:

package com.polaris.designpattern.list3.behavioral.pattern01.templatemethod.classicdemo;// 抽象類,定義了模板方法
abstract class AbstractClass {// 模板方法,定義了算法的框架  public final void templateMethod() {specificMethod1(); // 調用第一個抽象方法  // 可能還有其他的通用操作或條件判斷  specificMethod2(); // 調用第二個抽象方法  }// 抽象操作,子類必須實現  protected abstract void specificMethod1();// 另一個抽象操作,子類也必須實現  protected abstract void specificMethod2();
}// 具體子類A  
class ConcreteClassA extends AbstractClass {// 實現抽象操作  @Overrideprotected void specificMethod1() {System.out.println("ConcreteClassA.specificMethod1()");}// 實現抽象操作  @Overrideprotected void specificMethod2() {System.out.println("ConcreteClassA.specificMethod2()");}
}// 具體子類B  
class ConcreteClassB extends AbstractClass {// 實現抽象操作  @Overrideprotected void specificMethod1() {System.out.println("ConcreteClassB.specificMethod1()");}// 實現抽象操作  @Overrideprotected void specificMethod2() {System.out.println("ConcreteClassB.specificMethod2()");}
}// 客戶端代碼  
public class TemplateMethodTest {public static void main(String[] args) {AbstractClass classA = new ConcreteClassA();classA.templateMethod(); // 輸出 ConcreteClassA.specificMethod1() 和 ConcreteClassA.specificMethod2()  AbstractClass classB = new ConcreteClassB();classB.templateMethod(); // 輸出 ConcreteClassB.specificMethod1() 和 ConcreteClassB.specificMethod2()  }
}
/* Output:
ConcreteClassA.specificMethod1()
ConcreteClassA.specificMethod2()
ConcreteClassB.specificMethod1()
ConcreteClassB.specificMethod2()
*///~

在這個示例中,AbstractClass 是抽象類,它定義了一個模板方法 templateMethod(),該方法調用了兩個抽象操作 specificMethod1()specificMethod2()ConcreteClassAConcreteClassB 是具體子類,它們分別實現了這兩個抽象操作。客戶端代碼通過調用模板方法來執行算法,而具體的步驟(specificMethod1()specificMethod2())則由不同的子類實現。

模板方法模式(Template Method Pattern)是一種行為型設計模式,它定義了一個操作中的算法框架,而將一些步驟延遲到子類中。這使得子類可以不改變一個算法的結構即可重新定義該算法的某些特定步驟。

應用

模板方法模式在以下場景中特別有用:

  1. 算法復用:當多個類有相似的行為,但部分行為需要定制時,可以使用模板方法模式。
  2. 框架設計:在框架設計中,模板方法模式可以幫助實現一些可擴展的、可定制的框架。
  3. 一次性算法:如果一個算法很少改變,但其中的某些步驟可能需要根據具體情況進行定制時,可以使用模板方法模式。

優點

  1. 代碼復用:模板方法模式通過把不變行為搬到超類,去除了子類中的重復代碼。
  2. 擴展性好:子類可以通過實現或重寫抽象方法或鉤子方法來改變或擴展算法的部分行為。
  3. 靈活性高:在模板方法模式中,可以通過定義抽象方法和鉤子方法來實現算法的靈活性和可擴展性。
  4. 符合開閉原則:對擴展開放,對修改關閉。在模板方法模式中,增加新的功能可以通過增加新的子類來實現,而不需要修改現有的代碼。

缺點

  1. 抽象層次提高:模板方法模式會增加類的抽象層次,使得子類之間的關系更加復雜。
  2. 可能產生過多子類:如果每個不同的行為都使用子類來實現,那么類的個數可能會急劇增加。
  3. 性能考慮:由于使用了繼承,如果子類過多,可能會影響系統的性能。

使用場景

  1. 創建框架:當我們需要創建一個框架,并希望這個框架具有可擴展性和可定制性時,可以使用模板方法模式。
  2. 實現回調:在某些情況下,我們可能需要讓子類在特定的事件發生時執行一些操作,這時可以使用模板方法模式來實現回調。
  3. 資源初始化:當資源的初始化或清理具有固定的流程,但某些步驟可能需要根據具體情況進行定制時,可以使用模板方法模式。
  4. 算法復用:當多個類有相似的行為,但部分行為需要根據具體情況進行定制時,可以使用模板方法模式來復用代碼。

模板方法模式是一種非常實用的設計模式,它可以幫助我們更好地組織代碼,提高代碼的可維護性和可擴展性。

示例解析:以烹飪過程為例

假設我們有一個基本的烹飪流程,其中包含了預熱烤箱、烹飪食物和關閉烤箱的步驟。但不同的食物需要不同的烹飪時間和溫度,這部分就是可以定制的部分。

假設我們想要烤一個蛋糕和一個披薩。兩者都需要預熱烤箱,但烹飪時間和溫度不同,烹飪完成后都需要關閉烤箱。這里,預熱烤箱和關閉烤箱就是模板方法中固定的部分,而烹飪食物則是需要根據不同食物來定制的部分。

類圖

在這里插入圖片描述

代碼示例

package com.polaris.designpattern.list3.behavioral.pattern01.templatemethod.cookingdemo;// 抽象類,代表烹飪流程
abstract class CookingProcess {// 模板方法,定義了烹飪的整個過程  public final void cook() {preheatOven(); // 預熱烤箱  cookFood();    // 烹飪食物(需要子類實現)  turnOffOven(); // 關閉烤箱  }// 預熱烤箱的具體方法,不需要子類改變  protected void preheatOven() {System.out.println("Preheating oven to 350°F...");// 假設預熱完成需要一些時間,這里省略等待邏輯  }// 烹飪食物的方法,需要子類實現  protected abstract void cookFood();// 關閉烤箱的具體方法,不需要子類改變  protected void turnOffOven() {System.out.println("Turning off the oven...");}
}// 蛋糕烹飪類  
class CakeCooking extends CookingProcess {// 實現烹飪食物的方法,這里是烹飪蛋糕  @Overrideprotected void cookFood() {System.out.println("Baking cake for 30 minutes...");// 假設烹飪完成需要一些時間,這里省略等待邏輯  }
}// 披薩烹飪類  
class PizzaCooking extends CookingProcess {// 實現烹飪食物的方法,這里是烹飪披薩  @Overrideprotected void cookFood() {System.out.println("Baking pizza for 15 minutes at 450°F...");// 假設烹飪完成需要一些時間,這里省略等待邏輯  }
}// 客戶端代碼  
public class CookingDemo {public static void main(String[] args) {CookingProcess cakeCooking = new CakeCooking();cakeCooking.cook(); // 烹飪蛋糕  System.out.println("--------------------");CookingProcess pizzaCooking = new PizzaCooking();pizzaCooking.cook(); // 烹飪披薩  }
}
/* Output:
Preheating oven to 350°F...
Baking cake for 30 minutes...
Turning off the oven...
--------------------
Preheating oven to 350°F...
Baking pizza for 15 minutes at 450°F...
Turning off the oven...
*///~

這個例子展示了模板方法模式如何幫助我們在保持烹飪流程基本框架不變的情況下,為不同的食物定制不同的烹飪步驟。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/22303.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/22303.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/22303.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++linux下使用clog和重定向實現寫日志

Clinux下使用clog和重定向實現寫日志 實現文件基本功能測試編譯運行額外知識點 實現文件 LogUtil.hpp /** * 通用日志實現 * lsl * 2024-06-04 */#ifndef LOGUTIL_HPP #define LOGUTIL_HPP #include<iostream> #include <time.h> #include <cstring> #defi…

LED驅動IC:HC2161,升壓型LED恒流驅動ic,供應LED燈杯單節電池以上供電的LED燈串平板顯示LED背光大功率LED照明

LED驅動IC&#xff1a; HC2161:升壓型LED恒流驅動ic 概述&#xff1a;HC2161是一款高效率、高精度的升 壓型大功率LED恒流驅動控制芯片。 HC2161內置高精度誤差放大器&#xff0c;固 定關斷時間控制電路&#xff0c;恒流驅動電路等&#xff0c; 特別適合大功率、多個高亮…

七年

七年 我&#xff0c;回來了&#xff0c;七年后。回看之前的文章&#xff0c;當初的情意濃濃&#xff0c;患得患失&#xff0c;真的是恍如隔世。 經歷了重重波折&#xff0c;父母反對&#xff0c;奔赴廣州&#xff0c;云南危機&#xff0c;房名危機&#xff0c;都沒把我們拆散…

鴻蒙開發接口定制管理:【@ohos.configPolicy (配置策略)】

配置策略 配置策略提供按預先定義的定制配置層級獲取對應定制配置目錄和文件路徑的能力。 說明&#xff1a; 本模塊首批接口從API version 8開始支持。后續版本的新增接口&#xff0c;采用上角標單獨標記接口的起始版本。 本模塊接口均為系統接口&#xff0c;三方應用不支持調…

Kaggle平臺進行Python版本降級

前言 最近在復現語音合成模型VITS&#xff0c;由于目前沒有算力故去Kaggle白嫖運算資源。 VITS的運行環境要求如下 Cython0.29.21 librosa0.8.0 matplotlib3.3.1 numpy1.18.5 phonemizer2.2.1 scipy1.5.2 tensorboard2.3.0 torch1.6.0 torchvision0.7.0 Unidecode1.1.1截至2…

21.過擬合和欠擬合示例

1. 背景介紹 在機器學習和深度學習中&#xff0c;過擬合和欠擬合是兩個非常重要的概念。過擬合指的是模型在訓練數據上表現很好&#xff0c;但在新的測試數據上效果變差的情況。欠擬合則是指模型無法很好地擬合訓練數據的情況。這兩種情況都會導致模型無法很好地泛化&#xff…

視頻號小店,常見的違規條例!98%的商家必犯的違規細節!

哈嘍~我是電商月月 做電商&#xff0c;不管哪個平臺都有屬于自己的規則條例&#xff0c;這些違規細節&#xff0c;一定要提前了解 所以今天&#xff0c;月月就給大家分享一下&#xff0c;做視頻號小店的話&#xff0c;有哪些常見的違規細節 這里我們分三點講解 一&#xff…

【分享】兩種方法禁止修改Word文檔

對于比較重要的Word文件&#xff0c;不想被隨意編輯修改&#xff0c;可以試試以下兩個方法&#xff0c;不清楚的小伙伴&#xff0c;一起來看看吧&#xff01; 方法1&#xff1a;設置“只讀方式” 我們可以給Word文檔設置以“只讀方式”打開&#xff0c;這樣就算編輯修改了文檔…

如何通過SD-WAN提升企業溝通效率

在數字化飛速發展的今天&#xff0c;企業對大數據和實時商業數據傳輸的需求日益增長。傳統的專線連接技術已無法滿足企業對快速部署商業應用和高效網絡連接的需求。在這種背景下&#xff0c;SD-WAN成為提升企業網絡溝通效率的關鍵技術。 SD-WAN的靈活部署模式 SD-WAN提供了高度…

6月軟考新通知:24下集成大概率是中級蕞簡單的一門

2024下半年軟考6月新通知&#xff1a; 一、24下軟考考試時間安排&#xff1a; 24下半年軟考報名時間&#xff1a;8月19日-9月15日 24下半年軟考考試時間&#xff1a;11月9-12日 24下半年軟考成績查詢&#xff1a;12月中&#xff08;預計&#xff09; 二、考情分析 24上軟考…

09_JavaWeb會話

1.會話 HTTP是一種無狀態協議&#xff1b; HTTP協議對于發送過請求或者響應都不做持久化處理具體來說就是客戶端發送請求&#xff0c;服務器接收請求&#xff0c;但是服務器自身不會記錄每一條請求都是由哪一個客戶端發出的&#xff1b; 會話管理是通過Cookie和Session配合解…

【排序】插入排序,希爾排序

前面我們講述了冒泡排序和選擇排序&#xff0c;我們本章講的排序方法是插入排序&#xff0c;插入排序是希爾排序實現的基礎函數&#xff0c;大家一定要好好理解插入排序的邏輯&#xff0c;這樣才能在后面學習希爾排序的時候&#xff0c;更容易的去理解&#xff0c;我們直接開始…

關于無法通過腳本啟動Kafka集群的解決辦法

啟動Kafka集群時&#xff0c;需要在每臺個節點上啟動啟動服務&#xff0c;比較麻煩&#xff0c;通過寫了以下腳本來進行啟停&#xff1b;發現能正常使用停止功能&#xff0c;不能正常啟動Kafka&#xff1b; Kafka啟停腳本&#xff1a; ## 以防不能通過shell腳本啟動Kafka服務…

富格林:揭露黑幕平臺保障安全

富格林指出&#xff0c;很多黑幕平臺都會將自己包裝得光鮮亮麗后&#xff0c;再出來誘惑投資者&#xff0c;使得投資者資金安全得不到保障&#xff0c;有苦說不出。富格林表示&#xff0c;黑幕平臺的套路其實是非常常見的&#xff0c;只要投資者熟知并能夠分辨出&#xff0c;就…

C盤擴容——只能刪除C盤右邊的磁盤對C盤進行擴展

winR彈出命令框 輸入&#xff1a;compmgmt.msc 進入磁盤管理頁面 注意&#xff1a;被刪除盤如果有重要數據信息&#xff0c;請備份。 或者刪除之前轉移至其他盤&#xff0c;否則刪除之后&#xff0c;則無法找回。 尤其是安裝的軟件。 規范安裝目錄十分重要。 將C盤右邊的磁盤&a…

最全 Inno Setup 教程-[FILE] Flag參數

【1】此參數是一個附加選項的集合。可以使用空格將多個選項分隔開。 【2】支持以下選項&#xff1a; 32位 當在“Source”和“DestDir”參數中使用{sys}常量時&#xff0c;將該常量映射到32位系統目錄。將“regserver”和“regtypelib”標志設置為將文件視為32位&#xff0c;…

安防綜合管理系統EasyCVR視頻匯聚平臺GA/T 1400協議中的關鍵消息交互示例

在當今的信息化時代&#xff0c;公共安全防范日益成為保障社會和諧穩定的關鍵。視頻監控系統作為現代安全防范的重要手段&#xff0c;正不斷在公安、交通、城市管理等領域發揮著越來越重要的作用。而GA/T 1400協議視圖庫&#xff0c;作為公安視頻圖像信息應用系統的標準&#x…

Vue3 子組件訪問父組件的方法 - 父組件訪問子組件的屬性或方法 - 子組件修改父組件的值

一。子組件訪問父組件的方法 //父組件 <DialogEditing close-dialog"handleClose" /> const handleClose () > {};//子組件 const emit defineEmits(["closeDialog"]); const close () > {emit("closeDialog"); // 使用 };二。父…

健身日記之倒立俯臥撐學習——起始日2024.6.4

文章目錄 前言 自我介紹 昔日計劃 新目標計劃 瓶頸突破嘗試 參考視頻及文章 前言 有輕微健身基礎&#xff0c;正式接觸街健五大神技&#xff0c;立志在兩年內解鎖全部&#xff0c;將有機會的進行日常訓練和目標肌群鍛煉&#xff0c;這里向大家展示我的計劃和安排&#xf…

opencv-python(五)

opencv的顏色通道中順序是B&#xff0c;G&#xff0c;R。 圖像屬性 import cv2img cv2.imread(jk.jpg) print(fshape{img.shape}) print(fsize{img.size}) print(fdtype{img.dtype}) shape&#xff1a;圖像像素的行&#xff0c;列&#xff0c;通道 size&#xff1a;行數 X …