设计模式(C++)-行为型模式-模版方法模式
一、模版方法模式概述
模板方法模式:是一种行为型设计模式,它在父类中定义了一个算法的骨架,但将一些步骤的实现延迟到子类。模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。
简单来说:模版方法模式是定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模版方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定的步骤。
二、模版方法模式UML类图
模板方法场景
假如我们要做饮料,那么我们首先会定义一个做饮料的模板,即煮水->冲泡->导入杯中->加辅助材料,
具体煮什么水、冲泡什么东西放到子类中实现。然后定义一个模板方法,当我们要做饮料时就调用这个方法即可。
UML类图

三、代码实现
cpp
//template.h
#pragma once
/*
在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,
但是逻辑(算法)的框架(或通用的应用算法)是相同的。Template 提供了这种情况的一个实现框架。Template 模式是采用继承的
方式实现这一点:将逻辑(算法)框架放在抽象基类中,并定义好细节的接口,子类中实现细节
*/
/*
例子:假如我们要做饮料,那么我们首先会定义一个做饮料的模板,即煮水->冲泡->导入杯中->加辅助材料,
具体煮什么水、冲泡什么东西放到子类中实现。然后定义一个模板方法,当我们要做饮料时就调用这个方法即可。
*/
/*
模板方法模式:在父类中定义一个方法的抽象,由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中的执行次序。
*/
#include <iostream>
using namespace std;
//做饮料的模版
class DrinkTemplate
{
public:
//煮水
virtual void BoilWater() = 0;
//冲泡
virtual void Brew() = 0;
//导入杯中
virtual void PourInCup() = 0;
//加入辅助材料
virtual void AddSomething() = 0;
//模版方法
void Make() {
BoilWater();
Brew();
PourInCup();
AddSomething();
}
};
//做咖啡 实现做饮料模版
class Coffee :public DrinkTemplate {
public:
virtual void BoilWater() {
cout << "煮山泉水" << endl;
}
virtual void Brew() {
cout << "冲泡咖啡" << endl;
}
virtual void PourInCup() {
cout << "咖啡倒入杯中" << endl;
}
virtual void AddSomething() {
cout << "加糖,加牛奶" << endl;
}
};
//作茶 实现做饮料模版
class Tea :public DrinkTemplate {
public:
virtual void BoilWater() {
cout << "煮自来水" << endl;
}
virtual void Brew() {
cout << "冲泡菊花" << endl;
}
virtual void PourInCup() {
cout << "茶水倒入杯中" << endl;
}
virtual void AddSomething() {
cout << "加糖,加黑枸杞" << endl;
}
};
void testTemplate();
//template.cc
#include "template.h"
void testTemplate() {
cout << "=====Template Begin===================" << endl;
Tea *tea = new Tea();
tea->Make();
Coffee* coffee = new Coffee();
coffee->Make();
delete tea;
tea = nullptr;
delete coffee;
coffee = nullptr;
cout << "=====Template END=====================" << endl;
}
四、优缺点总结
优点:
- 代码复用最大化:公共代码提升到父类,编码代码重复
- 反向控制:"不要调用我们,我们会调用你"-父类控制流程,子类提供具体实现
- 符合开闭原则:新增新饮料类型只需要创建子类,无需修改现有代码
- 算法骨架保护:模板方法通常声明为final,防止子类破坏算法结构
- 提供钩子方法:允许子类可选地影响算法流程,增加灵活性。
缺点:
- 类的数量增加:每个不同的实现都需要一个子类,导致类的数量增多,系统复杂性增加
- 继承的局限性:
- 强耦合:子类和父类紧密耦合
- 单一继承限制:C++只支持单继承,限制了灵活性
- 违范里氏替换原则的风险:
- 潜在问题:子类可能修改父类的预期行为
- 难以理解算法流程
- 父类定义过多的抽象方法
- 违反组合由于继承原则
- 重构困难