C++设计模式——模板模式(Template Pattern)
微信公众号:幼儿园的学霸
目录
定义
Define the skeleton of an algorithm in an operation,deferring somesteps to subclass.Template Method lets subclasses redefine certain steps of analgorithm without changing the algorithm’s structure.
定义一个操作中的一个算法框架,把一些步骤推迟到子类去实现。模板方法模式让子类不需要改变算法结构而重新定义特定的算法步骤。
模板模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
当多个类有相同的方法,并且逻辑相同,只是细节上有差异时,可以考虑使用模板模式。具体的实现上可以将相同的核心算法设计为模板方法,具体的实现细节有子类实现。
将稳定的部分放到抽象类中,将变化的实现细节延时的子类中实现,这是模板模式最核心的思想
变与不变
模板模式是基于继承实现的
一个典型的模板模式UML类图如下:
其包含的角色有:
- AblstractClass(抽象类):在抽象类中定义了一系列的操作PrimitiveOperation,每个操作可以是具体的,也可以是抽象的,每个操作对应一个算法的步骤,在子类中可以重新定义或实现这些步骤。TmplateMethod()这个方法用于定义一个算法结构,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。
- ConcreteClass(具体子类):用于实现在父类中声明的抽象基本操作,也可以覆盖在父类中已经实现的具体基本操作。
代码示例
以生产电脑为例,电脑生产的过程都是一样的,只是一些装配的器件可能不同而已。
#include <bits/stdc++.h>
using std::cout;
using std::endl;
//
//模板模式
//
/*
* 关键代码:在抽象类实现通用接口,细节变化在子类实现。
* 变与不变
*/
class Computer {
public:
void product() {
installCpu();
installRam();
installGraphicsCard();
installHardisk();
}
virtual ~Computer() = default;
protected:
//将抽象行为放到子类实现
virtual void installCpu() = 0;
virtual void installRam() = 0;
virtual void installGraphicsCard() = 0;
private:
//公共的部分,不变
void installHardisk() {
std::cout << "Computer install 1TB hard disk !" << std::endl;
};
};
//子类实现父类所定义的一个或多个抽象方法
class ComputerA : public Computer {
protected:
void installCpu() override {
cout << "ComputerA install Inter Core i5" << endl;
}
void installRam() override {
cout << "ComputerA install 2G Ram" << endl;
}
void installGraphicsCard() override {
cout << "ComputerA install Gtx940 GraphicsCard" << endl;
}
};
class ComputerB : public Computer {
protected:
void installCpu() override {
cout << "ComputerB install Inter Core i7" << endl;
}
void installRam() override {
cout << "ComputerB install 4G Ram" << endl;
}
void installGraphicsCard() override {
cout << "ComputerB install Gtx960 GraphicsCard" << endl;
}
};
int main() {
std::shared_ptr<Computer> pComputerA = std::make_shared<ComputerA>();
pComputerA->product();
//C++14才引入进make_unique
std::unique_ptr<ComputerB> pComputerB = std::unique_ptr<ComputerB>(new ComputerB);
pComputerB->product();
return 0;
//运行结果
//ComputerA install Inter Core i5
//ComputerA install 2G Ram
//ComputerA install Gtx940 GraphicsCard
//Computer install 1TB hard disk !
//ComputerB install Inter Core i7
//ComputerB install 4G Ram
//ComputerB install Gtx960 GraphicsCard
//Computer install 1TB hard disk !
}
总结
优缺点
- 优点:
1.封装不变部分,扩展可变部分。
2.提取公共代码,便于维护。
3.行为由父类控制,子类实现。一句话: 实现代码的复用
- 缺点:
每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
模板模式和策略模式的区别
模板模式的主要思想:定义一个算法流程,将一些特定步骤的具体实现、延迟到子类。使得可以在不改变算法流程的情况下,通过不同的子类、来实现“定制”流程中的特定的步骤。
策略模式的主要思想:使不同的算法可以被相互替换,而不影响客户端的使用。
模板模式使用继承来解决问题,而策略模式使用的则是委托
模板模式就是提供了一个很好的代码复用平台。因为有时候,我们会遇到由一系列步骤构成的过程需要执行。这个过程从高层次上看是相同的,但是有些步骤实现可能不同。这时候,我们通常就应该要考虑用模板模式了。也就是说,当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模板模式把这些行为搬移到单一的地方,这样帮助子类摆脱重复的不变行为的纠缠。
参考资料
1.C++ 常用设计模式(学习笔记)
2.设计模式之模板方法模式(C++)
3.模板方法设计模式(Template Method)