1. 程式人生 > 實用技巧 >【設計模式】模板方法模式

【設計模式】模板方法模式

模板方法模式

簡介

模板方法模式是教簡單且常用的一種設計模式,是基於類的繼承的一種程式碼複用技術,其結構只存在基類和派生類之間的繼承關係。模板方法是一個具體的方法,給出了一個頂層邏輯流程框架。

模板方法模式:定義一個操作中的演算法的框架,而將一些步驟延遲到子類中,使得子類可以不改變一個演算法的結構即可重新定義該演算法的某些特定的步驟。子類實現的具體方法叫作基本方法,實現對基本方法高度的框架方法,叫作模板方法。

結構

實現

#ifndef __DEMO_H__
#define __DEMO_H__

// 抽象類(基類)
class AbstractClass {
public:
    void templateMethod() {
        // do something
        method1();
        method2();
        method3();
    }

    // 基本方法-公共方法
    void method1() {
        // do something
    }

    // 基本方法2
    virtual void method2() = 0;

    // 基本方法3-預設實現
    void method3() {
        // do something
    }
};

// 具體類(派生類)
class ConceteClass: public AbstractClass {
public:
    // 
    void method2() {
        // do something
    }

    //
    void method3() {
        // do something
    }
};


#endif

例項

問題描述

某個指紋處理模組可以在兩種模式下處理演算法,即安全模式和非安全模式。在安全模式下,為了保證資料安全,某個指紋識別流程需要對採得的指紋影象進行加密,在處理影象之前再對加密資料進行解密。而非安全模式這不需要加密解密過程。指紋演算法流程如下:採圖——加密——解密——演算法處理指紋——處理結果。現用模板方法模式模擬上述過程。

問題解答

// FingerprintModule.h

// 基類
class FingerprintModule
{
public:
	FingerprintModule(){}
	void getImage(){
		printf("採指紋影象\n");
	}
	void output(){
		printf("指紋影象處理完成!\n");
	}
	virtual bool isSafeMode() = 0;
	virtual void processImage() = 0;
	// 加解密
	virtual void encrypt() = 0;
	virtual void decrypt() = 0;
 
	// 模板方法
	void algorithm(){
		// 1.採圖
		getImage();
		// 2.安全模式下加密和解密
		if (isSafeMode()){
			// 2.1. 加密
			encrypt();
			// 2.2. 解密
			decrypt();
		}
		// 3.處理Image
		processImage();
		// 4.處理結果
		output();
	}
};

// 派生類
class FingerprintModuleA :public FingerprintModule
{
public:
	FingerprintModuleA(){}
	void processImage(){
		printf("使用 第一代版本演算法 處理指紋影象\n");
	}
	bool isSafeMode(){
		printf("安全模式\n");
		return true;
	}
	void encrypt(){
		printf("使用RSA金鑰加密\n");
	}
	void decrypt(){
		printf("使用RSA金鑰解密\n");
	}
};
 
// 派生類
class FingerprintModuleB :public FingerprintModule
{
public:
	FingerprintModuleB(){}
	void processImage(){
		printf("使用 第二代版本演算法 處理指紋影象\n");
	}
	bool isSafeMode(){
		printf("非安全模式\n");
		return false;
	}
	void encrypt(){}
	void decrypt(){}
};
 
// 派生類
class FingerprintModuleC :public FingerprintModule
{
public:
	FingerprintModuleC(){}
	void processImage(){
		printf("使用 第一代版本演算法 處理指紋影象\n");
	}
	bool isSafeMode(){
		printf("安全模式\n");
		return true;
	}
	void encrypt(){
		printf("使用DH金鑰加密\n");
	}
	void decrypt(){
		printf("使用DH金鑰解密\n");
	}
};
// example.cpp

#include "FingerprintModule.h"
 
int main(int argc, char *argv[])
{
	FingerprintModule *fp = new FingerprintModuleA();
	fp->algorithm();

    printf("\n");
 
	fp = new FingerprintModuleB();
	fp->algorithm();

    printf("\n");
 
	fp = new FingerprintModuleC();
	fp->algorithm();
 
	return 0;
}

總結

優點

  • 在基類中定義演算法的框架,並宣告一些流程方法,有具體派生類實現具體細節,派生類中的實現並不會影響基類定義的演算法的框架流程。
  • 公共行為在基類中提供實現,有利於程式碼複用。
  • 派生類可以覆蓋基類的方法,重新實現某些方法,具有靈活性。
  • 可以很方便的擴充套件和更換派生類而不影響基類和其他派生類。符合開閉原則和單一職責原則

缺點

  • 模板方法模式在抽象類中定義了子類的方法,即子類對父類產生了影響,部分影響了程式碼的可讀性。
  • 模板方法中的步驟過多,其維護工作就可能會越困難。

場景

  • 分割開復雜演算法,可以將演算法的框架流程定義在基類中,設計為模板方法,而具體的細節由派生類設計實現。例如機器學習中的監督學習演算法有很多,如決策樹、KNN、SVN等,但其流程大致相同,都包括輸入樣本、擬合、預測等過程,把這些過程提取出來,構造模板方法,並通過鉤子方法控制流程。
  • 各個派生類的公共部分提取到基類中,以實現程式碼複用。
  • 派生類需要覆蓋基類的某些方法。

與其他模式的關係

  • 工廠方法模式模板方法模式的一種特殊形式。同時,工廠方法可以作為一個大型模板方法中的一個步驟。
  • 模板方法基於繼承機制:她允許你通過擴充套件子類中的部分內容來改變部分演算法。而策略模式基於組合機制:你可以通過對相應行為提供不同的策略來改變物件的部分行為。模板方法模式在類層次上運作,因此它是靜態的。而策略模式在物件層次上執行,因此執行在執行時切換行為。