設計模式(十):模板方法模式

来源:http://www.cnblogs.com/jenkinschan/archive/2016/08/14/5768760.html
-Advertisement-
Play Games

一、概述 模板方法模式在一個方法中定義一個演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變演算法結構的情況下,重新定義演算法中的某些步驟。 二、結構類圖 三、解決問題 模板方法就是提供一個演算法框架,框架裡面的步驟有些是父類已經定好的,有些需要子類自己實現。相當於要去辦一件事情,行動的流 ...


一、概述

  模板方法模式在一個方法中定義一個演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變演算法結構的情況下,重新定義演算法中的某些步驟。

二、結構類圖

  

 

三、解決問題

  模板方法就是提供一個演算法框架,框架裡面的步驟有些是父類已經定好的,有些需要子類自己實現。相當於要去辦一件事情,行動的流程已經定好了,但有些步驟需要自己去做,而有些步驟可能別人幫我們做了。就拿建網站來說,一般的程式是購買功能變數名稱-->購買空間-->上傳網站-->備案-->審核,每個網站的創建必須經過這樣的固定程式,但除了審核不用建站者關心,其他的步驟都要建站者自己去完成。

四、應用實例

  現在我們很多家庭都有了豆漿機,豆漿的營養價值不用我多說了。製作豆漿的程式簡單點來說就是選材--->添加配料--->浸泡--->放到豆漿機打碎,通過添加不同的配料,可以製作出不同口味的豆漿,但是選材、浸泡和放到豆漿機打碎這幾個步驟對於製作每種口味的豆漿都是一樣的。

  1、創建抽象類

package templatemethod.pattern;

//豆漿類,抽象類
public abstract class SoyaMilk {
	//這是模板方法,用final修飾,不允許子類覆蓋。模板方法定義了製作豆漿的程式
	final void  prepareRecipe(){
		selectMaterial();
		addCondiments();
		soak();
		beat();
	}
	
	//選材方法,選擇黃豆
	void selectMaterial(){
		 System.out.println("第一步、選擇好了新鮮黃豆");
	}
	
	//可以添加不同的配料,在這裡設置為抽象方法,子類必須實現
	abstract void addCondiments();
	
	//浸泡
	void soak(){
		System.out.println("第三步、黃豆和配料開始浸泡,大概需要5個小時");
	}
	
	//放到豆漿機打碎
	void beat(){
		System.out.println("第四步、黃豆的配料放到豆漿機打碎");
	}
	
}

  2、創建紅棗豆漿

package templatemethod.pattern;

//紅棗豆漿
public class ReddatesSoyaMilk extends SoyaMilk{
	//實現父類的添加配料方法
	@Override
	void addCondiments() {
		System.out.println("第二步、添加紅棗配料");
		
	}
	
}

  3、創建核桃豆漿

package templatemethod.pattern;

//核桃豆漿
public class NutSoyaMilk extends SoyaMilk{
	//實現父類的添加配料方法
	@Override
	void addCondiments() {
		System.out.println("第二步、添加核桃配料");		
	}

}

  4、測試製作豆漿

package templatemethod.pattern;

public class SoyaMilkTest {
	public static void main(String[] args){
		//製作紅棗豆漿
		System.out.println();
		System.out.println("-----製作紅棗豆漿步驟-------");
		SoyaMilk reddatesSoyaMilk = new ReddatesSoyaMilk();
		reddatesSoyaMilk.prepareRecipe();
		
		//製作核桃豆漿
		System.out.println();
		System.out.println("-----製作核桃豆漿步驟-------");
		SoyaMilk nutSoyaMilk = new NutSoyaMilk();
		nutSoyaMilk.prepareRecipe();
		
	}
}

  運行結果:

五、優缺點

  1、優點

  (1)、演算法只存在於一個地方,也就是在父類中,容易修改。需要修改演算法時,只要修改父類的模板方法或者已經實現的某些步驟,子類就會繼承這些修改。

  (2)、實現了最大化代碼復用。父類的模板方法和已實現的某些步驟會被子類繼承而直接使用。

  (3)、既統一了演算法,也提供了很大的靈活性。父類的模板方法確保了演算法的結構保持不變,同時由子類提供部分步驟的實現。

  (4)、提供了一個基本框架,容易擴展子類。模板方法有框架控制如何做事情,而由使用框架的人指定框架演算法中每個步驟的細節。子類只要繼承父類,實現抽象方法,就可以使用父類的演算法。

  2、缺點

  (1)、模板方法使用繼承方式復用代碼,如果要在基本演算法裡面增加一個步驟,而該步驟是抽象的話,每個子類都要修改代碼,實現這個步驟。

六、模板方法中的鉤子方法

  在模板方法模式的父類中,我們可以定義一個方法,它預設不做任何事,子類可以視情況要不要覆蓋它,該方法稱為“鉤子”。我們還是用上面做豆漿的例子來講解。

  1、創建有鉤子方法的父類

package templatemethod.pattern;

//豆漿類,抽象類
public abstract class SoyaMilkWithHook {
	//這是模板方法,用final修飾,不允許子類覆蓋。模板方法定義了製作豆漿的程式
	final void  prepareRecipe(){
		selectMaterial();
		//判斷是否添加配料
		if(customerWantsCondiments()){
			addCondiments();
		}		
		soak();
		beat();
	}
	
	//選材方法,選擇黃豆
	void selectMaterial(){
		 System.out.println("選擇好了新鮮黃豆");
	}
	
	//可以添加不同的配料,在這裡設置為抽象方法,子類必須實現
	abstract void addCondiments();
	
	//浸泡
	void soak(){
		System.out.println("材料開始浸泡,大概需要5個小時");
	}
	
	//放到豆漿機打碎
	void beat(){
		System.out.println("材料放到豆漿機打碎");
	}
	
	//鉤子方法,是否添加配料
	boolean customerWantsCondiments(){
		return true;
	}
}

  2、創建純豆漿子類

package templatemethod.pattern;

//製作純豆漿,不添加任何配料
public class PureSoyaMilk extends SoyaMilkWithHook{

	@Override
	void addCondiments() {
		
	}
	
	//覆蓋鉤子方法,不添加配料
	@Override
	boolean customerWantsCondiments(){
		return false;
	}
}

  3、測試製作純豆漿

package templatemethod.pattern;

public class PureSoyaMilkTest {
	public static void main(String[] args){
		//製作純豆漿
		System.out.println();
		System.out.println("-----製作純豆漿步驟-------");
		SoyaMilkWithHook pureSoyaMilk = new PureSoyaMilk();
		pureSoyaMilk.prepareRecipe();
	}
}

  測試結果:

  鉤子方法的作用

  1、讓子類實現演算法中的可選部分。演算法中的某些步驟是可選的,子類可以做出決定是否需要這些步驟。

  2、如果鉤子對於子類的實現不重要時,子類可以對鉤子置之不理。

  3、鉤子可以讓子類能夠有機會對模板方法中某些即將發生的(或剛剛發生的)步驟作出反應。可以在鉤子中實現我們對於某個步驟執行需要作出的動作,模板方法的某個步驟執行時,調用鉤子。

七、模板方法與策略的比較

  1、相同點

  (1)、都封裝了演算法。

  2、不同點

  (1)、策略使用組合方式實現演算法,客戶可以自由選擇演算法;模板方法使用繼承方式獲得演算法,確保演算法的基本結構不變。

  (2)、策略代碼復用程度低,每個演算法都要對應一個類;模板方法代碼復用高,子類可以繼承父類的代碼。  

  (3)、策略依賴少,自己實現整個演算法;模板方法依賴高,子類依賴父類中的方法的實現。

八、使用場景

  1、當要完成一件事情,它有固定的程式流程,但某些步驟是自定義的,使用模板方法。

  2、當需要創建框架時,在超類中提供一個基礎的方法,達到代碼的復用,並允許子類指定行為。

 


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

-Advertisement-
Play Games
更多相關文章
  • 一、Bean的生命周期 Spring IOC容器可以管理Bean的生命周期,允許在Bean生命周期的特定點執行定製的任務。 Spring IOC容器對Bean的生命周期進行管理的過程如下: (1).通過構造器或工廠方法創建Bean實例。 (2).為Bean的屬性設置值和對其它Bean的引用。 (3) ...
  • 此圖是 java 中 Collection 相關的介面與類的關係的類圖。其中,類只是集合框架的一部分,比較常用的一部分。 第一次畫類圖,著實很費勁,不過收穫也不小。 下麵是相關介面和類的解釋說明。文字來自 JDK API 1.6 中文版。原諒我的懶惰,實在不想自己寫,太麻煩。如有錯誤,還請指正。 如 ...
  • 查看現有tomcat的記憶體大小情況1、啟動tomcat 2、訪問 http://localhost:8080/manager/status ,並輸入您在安裝tomcat時輸入的用戶與口令,如 admin ,密碼 admin(密碼是您在tomcat安裝時輸入的) 註:添加用戶,修改conf/tomca ...
  • 面試的時候經常會問到Java的單例模式,這道題能很好的考察候選人對知識點的理解程度。單例模式要求在系統運行時,只存在唯一的一個實例對象。 下麵我們來詳細剖析一下其中的關鍵知識點,並介紹五種實現方法,以及它們的優缺點。 一、最簡單的方法是在類載入的時候初始化這個單獨的實例。 首先,定義單例類(沒有特別 ...
  • 一.什麼是集合 集合是對象的集合,就像數組是數的集合。集合是一種容器,可以存放對象(可以是不同類型的對象)。 二.集合的優點(為什麼要用集合) 當然,在java里,可以使用數組來存放一組類型相同的對象。但是數組存放對象有兩個缺點(集合優點): 三.集合的實現 java中集合主要由兩個介面實現:Col ...
  • 1.清屏 Ctrl + L 2.退出 q() 3.設置工作空間 getwd() setwd('D:\\Program Files\\RStudio\\workspace') 4.顯檔當前工作目錄下的文件列表 list.files() choose.dir() dir("D:\\Program Fil... ...
  • 簡單值 一半頂層settings元素是簡單值,它們表示的一系列值可以配置Maven的核心行為:settings.xml中的簡單頂層元素 < settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http://www.w3.org ...
  • 前兩天偷懶,沒有堅持,今天開始,希望能堅持下去, 今天主要學習的是數據類型,關於python,數據類型主要有整型(int)、布爾類型(bool)、浮點型(float)、E記法(E) 舉例說明,整型(int)主要為整數,布爾類型(bool)為判斷,true或者false。浮點型(float)包含小數點 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...