Template Methods 模板方法:定義一個操作中的算法的骨架,而再將一些步驟延遲到子類中,TemplateMethod 使得子類不改變一個算法的結構即可重定義該算法的某特定步驟。TemplateMethos 模式解決的是和 Strategy 模式類似的問題,Template 將邏輯算法框架放在抽象基類中,並定義好細節的接口,子類中實現細節,即用繼承的方式實現。而 Strategy 模式將邏輯算法封裝到一個類中,並採取組合(委託)的方式解決問題。
TemplateMethod 模板方法適用於:1.一次性實現一個算法的不變部分,並將可變的行爲留給子類來實現。2.各子類中公共的行爲應該被提取出來並集中到一個公共父類中以避免代碼重複。3.控制子類擴展,模板方法只在特定點調用鉤子操作“hook”,這樣允許在這些點進行擴展。
TemplateMethod 模板方法模式的通用結構如下:
參與者:
AbstractClass:定義抽象的原語操作(primitive operation),具體的子類將重定義它們以實現一個算法的各個步驟。實現一個模板方法,定義一個算法的骨架,該模板方法不僅調用原語操作,也調用定義在 AbstractClass 或其它對象中的操作。
ConcreteClass:實現原語操作以完成算法中特定於子類相關的步驟。
ConcreteClass 靠 AbstractClass 實現算法中不變的步驟。模板方法是一種代碼利用技術,在類庫中尤爲重要,它們提取了類庫中的公共行爲。
關於鉤子操作(hook operation):它提供了缺省的行爲,子類可以在必要時進行擴展,一個鉤子操作在缺省操作通常是一個空操作。ParentClass 本身的 HookOperation 什麼也不做:
void ParentClass::HookOperation(){ }
void ParentClass::Operation(){
//父類的操作
HookOperation();
}
//子類可以重定義這個鉤子操作
void DerivedClass::HookOperation(){
//子類的擴展
}
鉤子操作是面向對象系統中分析和設計的一個原則:DIP(依賴倒置,Dependency Inversion Principles),獲得一種反向控制的效果,其含義是父類調用子類的操作(高層模塊調用低層模塊的操作),低層模塊實現高層模塊聲明的接口。這樣控制權在高層模塊,低層模塊反而要依賴高層模塊。
TemplateMethods 模板方法代碼示例:
1: //TemplateMethod.h
2: #pragma once
3:
4: // 抽象基類,定義算法的輪廓
5: class AbstractClass
6: {
7: public:
8: AbstractClass(){}
9: virtual ~AbstractClass(){}
10:
11: // 這個函數中定義了算法的輪廓
12: void TemplateMethod();
13: protected:
14: // 純虛函數,由派生類實現之
15: virtual void PrimitiveOperation1() = 0;
16: virtual void PrimitiveOperation2() = 0;
17: };
18:
19: // 繼承自AbstractClass,實現算法
20: class ConcreateClassA : public AbstractClass
21: {
22: public:
23: ConcreateClassA(){}
24: virtual ~ConcreateClassA(){}
25:
26: protected:
27: virtual void PrimitiveOperation1();
28: virtual void PrimitiveOperation2();
29: };
30:
31: // 繼承自AbstractClass,實現算法
32: class ConcreateClassB : public AbstractClass
33: {
34: public:
35: ConcreateClassB(){}
36: virtual ~ConcreateClassB(){}
37:
38: protected:
39: virtual void PrimitiveOperation1();
40: virtual void PrimitiveOperation2();
41: };
1:
2: #include "TemplateMethod.h"
3: #include <iostream>
4:
5: void AbstractClass::TemplateMethod()
6: {
7: PrimitiveOperation1();
8: PrimitiveOperation2();
9: }
10: /////
11: void ConcreateClassA::PrimitiveOperation1()
12: {
13: std::cout << "PrimitiveOperation1 by ConcreateClassA"
14: << std::endl;
15: }
16:
17: void ConcreateClassA::PrimitiveOperation2()
18: {
19: std::cout << "PrimitiveOperation2 by ConcreateClassA"
20: << std::endl;
21: }
22:
23: ////
24: void ConcreateClassB::PrimitiveOperation1()
25: {
26: std::cout << "PrimitiveOperation1 by ConcreateClassB"
27: << std::endl;
28: }
29:
30: void ConcreateClassB::PrimitiveOperation2()
31: {
32: std::cout << "PrimitiveOperation2 by ConcreateClassB"
33: << std::endl;
34: }
35:
1: //test.cpp
2: #include "TemplateMethod.h"
3: #include <iostream>
4:
5: int main()
6: {
7: AbstractClass* pConcreateClassA = new ConcreateClassA;
8: AbstractClass* pConcreateClassB = new ConcreateClassB;
9:
10: pConcreateClassA->TemplateMethod();
11: pConcreateClassB->TemplateMethod();
12:
13: delete pConcreateClassA;
14: delete pConcreateClassB;
15:
16: return EXIT_SUCCESS;
17: }