一、設計模式-模板方法
1、簡單介紹
簡單來說,就是先在父類中定義好一個函數,然後這個函數代表了一個操作,函數的內部調用了若干個已經實現的函數、未實現的函數,和這些函數在函數中的執行流程構成了函數的整體框架,其中
- 函數象徵了操作的整體流程
- 函數象徵了操作中既定的步驟,所有不同主體的操作中的這些步驟都相同
- 函數象徵了操作中未定的步驟,存在不同主體的操作中的這些步驟不相同
這樣的設計下,我們可以根據不同的場景來設計子類的函數的具體內容。父類往往是抽象類。
模板方法的整體思想是,對於某個操作,先在父類中定義好其算法的整體框架,然後將框架中的步驟延遲到子類裏面去實現。
這樣做的好處是,算法的整體框架已經定下來了,對於相似操作的不同步驟可以在子類中給出具體的實現。
- 在子類中不需要重寫出共同的重複步驟,代碼複用性強
- 在子類中也改變不了整體框架(或者說是運行流程),整體結構性強。
2、框架演示
UML圖示
代碼
// 抽象父類——F
class F
{
public:
void process_whole() // 整體的操作
{
common_step_1(); // 共同步驟1
common_step_2(); // 共同步驟2
especial_step_1(); // 【待實現】不同步驟1
especial_step_2(); // 【待實現】不同步驟2
common_step_etc(); // 共同步驟...
especial_step_etc(); // 【待實現】不同步驟...
especial_step_m(); // 【待實現】不同步驟m
common_step_n(); // 共同步驟n
}
protected:
virtual void especial_step_1() = 0; // 不同步驟1
virtual void especial_step_2() = 0; // 不同步驟2
virtual void especial_step_etc() = 0; // 不同步驟...
virtual void especial_step_m() = 0; // 不同步驟m
private:
void common_step_1() { } // 共同步驟1
void common_step_2() { } // 共同步驟2
void common_step_etc() { } // 共同步驟...
void common_step_n() { } // 共同步驟n
};
// 實現子類——S1
class S1 : public F
{
virtual void especial_step_1()
{
// 【S1具體實現】不同步驟1
}
virtual void especial_step_2() = 0
{
// 【S1具體實現】不同步驟2
}
virtual void especial_step_etc() = 0
{
// 【S1具體實現】不同步驟...
}
virtual void especial_step_m() = 0
{
// 【S1具體實現】不同步驟m
}
};
// 實現子類——S2
class S2 : public F
{
virtual void especial_step_1()
{
// 【S2具體實現】不同步驟1
}
virtual void especial_step_2() = 0
{
// 【S2具體實現】不同步驟2
}
virtual void especial_step_etc() = 0
{
// 【S2具體實現】不同步驟...
}
virtual void especial_step_m() = 0
{
// 【S2具體實現】不同步驟m
}
};
3、實際案例
案例:
現在設計一個父類爲動物飼養員AnimalRaiser,有一個函數feed功能是爲動物餵食,餵食的過程分爲:
- 拿出飯碗
- 放上食物
- 等待動物食用完畢
- 回收飯碗洗乾淨
由於每個動物食用的食物不同,需要根據動物的種類餵食不同的飼料,比如給狗狗餵食排骨,給貓咪餵食清蒸魚。(假設其他步驟對所有動物均相同)
另外設計兩個類——狗狗飼養員DogRaiser、貓咪飼養員CatRaiser.
UML圖示
AnimalRaiser類
-
AnimalRaiser.h
#ifndef ANIMALRAISER_H #define ANIMALRAISER_H class AnimalRaiser { public: AnimalRaiser(); virtual ~AnimalRaiser(); void feed(); protected: virtual void push_food() = 0; private: void prepare_bowl(); void wait_eat(); void clear_bowl(); }; #endif // !ANIMALRAISER_H
-
AnimalRaiser.cpp
#include "pch.h" #include "AnimalRaiser.h" #include <iostream> using namespace std; AnimalRaiser::AnimalRaiser() { } AnimalRaiser::~AnimalRaiser() { } void AnimalRaiser::feed() { prepare_bowl(); push_food(); wait_eat(); clear_bowl(); } void AnimalRaiser::prepare_bowl() { cout << "正在準備飯碗..." << endl; } void AnimalRaiser::wait_eat() { cout << "正在等待食用完畢..." << endl; } void AnimalRaiser::clear_bowl() { cout << "正在回收飯碗並清洗..." << endl; }
CatRaiser類
-
CatRaiser.h
#include "AnimalRaiser.h" #ifndef CATRAISER_H #define CATRAISER_H class CatRaiser : public AnimalRaiser { public: CatRaiser(); virtual ~CatRaiser(); protected: virtual void push_food(); }; #endif // !CATRAISER_H
-
CatRaiser.cpp
#include "pch.h" #include "CatRaiser.h" #include <iostream> using namespace std; CatRaiser::CatRaiser() { } CatRaiser::~CatRaiser() { } void CatRaiser::push_food() { cout << "正在往碗裏放上貓咪最愛吃的清蒸魚..." << endl; }
DogRaiser類
-
DogRaiser.h
#include "AnimalRaiser.h" #ifndef DOGRAISER_H #define DOGRAISER_H class DogRaiser : public AnimalRaiser { public: DogRaiser(); virtual ~DogRaiser(); protected: virtual void push_food(); }; #endif // !DOGRAISER_H
-
DogRaiser.cpp
#include "pch.h" #include "DogRaiser.h" #include <iostream> using namespace std; DogRaiser::DogRaiser() { } DogRaiser::~DogRaiser() { } void DogRaiser::push_food() { cout << "正在往碗裏放上狗狗最愛吃的排骨..." << endl; }
Main
- Main.cpp
#include "pch.h" #include "CatRaiser.h" #include "DogRaiser.h" #include <iostream> using namespace std; int main() { CatRaiser cr1; DogRaiser dr1; AnimalRaiser* arp; arp = &cr1; arp->feed(); cout << "------------------------------------" << endl; arp = &dr1; arp->feed(); return 0; }
執行結果
正在準備飯碗...
正在往碗裏放上貓咪最愛吃的清蒸魚...
正在等待食用完畢...
正在回收飯碗並清洗...
------------------------------------
正在準備飯碗...
正在往碗裏放上狗狗最愛吃的排骨...
正在等待食用完畢...
正在回收飯碗並清洗...