一、设计模式-模板方法
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; }
执行结果
正在准备饭碗...
正在往碗里放上猫咪最爱吃的清蒸鱼...
正在等待食用完毕...
正在回收饭碗并清洗...
------------------------------------
正在准备饭碗...
正在往碗里放上狗狗最爱吃的排骨...
正在等待食用完毕...
正在回收饭碗并清洗...