【学习笔记】C/C++ 设计模式 - 模板模式
介绍说明
模板设计模式是一种非常简单的设计模式,其主要是利用了虚函数的特性实现。非常适合应用在一些算法、流程、业务逻辑是固定的形式,其中某些步骤的实现方式又无法确定下来的场景。
举例说明
以下为模拟某芯片基于串口通信的固件升级代码,可以提供一个 FirmwareUpgrade 的类用于使用者集成。考虑到跨平台,该类的串口操作接口声明为纯虚函数,由使用者自己根据所用平台实现,而不需要关注具体的升级细节。
class FirmwareUpgrade
{
protected:
// 具体的串口操作实现延迟到子类实现
// 在不同的平台下, 提供对应平台的串口操作实现即可
virtual bool openSerialPort(int nBaudRate, int nDataBit, int nStopBit, int nParityBit) = 0;
virtual bool wrtieSerialPort(void *pOutBuffer, size_t nLength) = 0;
virtual size_t readSerialPort(void *pInBuffer, size_t size) = 0;
virtual bool closeSerialPort() = 0;
public:
FirmwareUpgrade() {};
virtual ~FirmwareUpgrade() {};
// 开始升级
bool upgrade(const char *pFirmwareFile) {
init();
...
enterUpgradeMode();
...
erasePartition();
...
updatePartition(pFirmwareFile);
...
verifyPartition();
...
resetDevice();
...
release();
return true;
}
private:
bool sendCommand(int cmd, void *pdata, size_t size) {
if (!wrtieSerialPort(package, sizeof(package))) {
return false;
}
if(readSerialPort(package, sizeof(package))) {
return false;
}
return package->done;
}
bool init(){
...
if (!openSerialPort(115200, 8, 1, 0)) {
return false;
}
...
return true;
}
bool enterUpgradeMode(){
...
}
bool erasePartition(){
...
}
bool updatePartition(const char *pFirmwareFile){
FILE fp = fopen(pFirmwareFilel, "rb");
...
while (fread(buffer, sizeof(buffer), 1, fp) == 1)
{
if (!sendCommand(update_COMMAND, NULL, 0)) {
fclose(fp);
return false;
}
}
...
fclose(fp);
return true;
}
bool verifyPartition() {
...
}
bool resetDevice(){
...
}
bool release() {
...
return closeSerialPort();
}
};
如 Windows 平台开发者,只需要利用 Windows 平台下接口实现串口的打开、写入、读取、关闭四个接口即可:
class FirmwareUpgradeWin : public FirmwareUpgrade
{
private:
virtual bool openSerialPort(int nBaudRate, int nDataBit, int nStopBit, int nParityBit)
{
com_handle = CreateFile("//.//COM9", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (com_handle != INVALID_HANDLE_VALUE){
...
}
...
}
virtual bool wrtieSerialPort(void *pOutBuffer, size_t nLength)
{
if (com_handle != INVALID_HANDLE_VALUE)
{
DWORD NumberOfBytesWrite;
if (!WriteFile(com_handle, buffer, length, &NumberOfBytesWrite, NULL))
{
DWORD error = GetLastError();
printf("error:%d\n", error);
}
return NumberOfBytesWrite;
}
}
virtual size_t readSerialPort(void *pInBuffer, size_t size)
{
if (com_handle != INVALID_HANDLE_VALUE)
{
DWORD NumberOfBytesRead;
ReadFile(com_handle, buffer, length, &NumberOfBytesRead, NULL);
return NumberOfBytesRead;
}
return 0;
}
virtual bool closeSerialPort()
{
// 关闭硬件接口
if (com_handle != INVALID_HANDLE_VALUE)
{
CloseHandle(com_handle);
}
}
public
bool upgrade(const char *pFirmwareFile) {
return FirmwareUpgrade::upgrade(pFirmwareFile);
}
};
int main()
{
FirmwareUpgradeWin mFirmwareUpgrade;
mFirmwareUpgrade.upgrade("d:\\xxxx.bin");
return 0;
}
如 Linux 平台下的实现:
class FirmwareUpgradeLinux : public FirmwareUpgrade
{
private:
virtual bool openSerialPort(int nBaudRate, int nDataBit, int nStopBit, int nParityBit)
{
m_fd = ::open(device_node, O_RDWR | O_NOCTTY);
....
tcgetattr(m_fd, &m_options);
....
return true;
}
virtual bool wrtieSerialPort(void *pOutBuffer, size_t nLength)
{
...
byte = write(m_fd, pOutBuffer, nLength));
...
return true;
}
virtual size_t readSerialPort(void *pInBuffer, size_t size)
{
...
select(m_fd + 1, &fs_read, NULL, NULL, &time);
...
byte = read(m_fd, data, size);
...
return byte;
}
virtual bool closeSerialPort()
{
...
close(m_fd);
...
return true
}
public:
bool upgrade(const char *pFirmwareFile) {
return FirmwareUpgrade::upgrade(pFirmwareFile);
}
};
int main()
{
FirmwareUpgradeLinux mFirmwareUpgrade;
mFirmwareUpgrade.upgrade("d:\\xxxx.bin");
return 0;
}
总结说明
主要就是将差异化的抽离出来,延迟到子类实现,而固定的逻辑处理则由父类封装并提供接口。相当于定义一个模板,子类只要按照这个模板实现相应的接口,由父类反向调用子类所实现的接口,来完成具体的逻辑功能。这样使用者不需要关心具体的升级逻辑实现,只需要按照要求完成相应的接口,即可使用升级功能,从而降低复杂性,又提升了灵活性。
【学习笔记】C/C++ 设计模式 - 模板模式的更多相关文章
- 【设计模式】Java设计模式 - 模板模式
Java设计模式 - 模板模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...
- 12. 星际争霸之php设计模式--模板模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- Django 学习笔记(五)模板标签
关于Django模板标签官方网址https://docs.djangoproject.com/en/1.11/ref/templates/builtins/ 1.IF标签 Hello World/vi ...
- Django 学习笔记(四)模板变量
关于Django模板变量官方网址:https://docs.djangoproject.com/en/1.11/ref/templates/builtins/ 1.传入普通变量 在hello/Hell ...
- Django 学习笔记(三)模板导入
本章内容是将一个html网页放进模板中,并运行服务器将其展现出来. 平台:windows平台下Liunx子系统 目前的目录: hello ├── manage.py ├── hello │ ├── _ ...
- 并发编程学习笔记(9)----AQS的共享模式源码分析及CountDownLatch使用及原理
1. AQS共享模式 前面已经说过了AQS的原理及独享模式的源码分析,今天就来学习共享模式下的AQS的几个接口的源码. 首先还是从顶级接口acquireShared()方法入手: public fin ...
- Redis学习笔记八:集群模式
作者:Grey 原文地址:Redis学习笔记八:集群模式 前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是 ...
- 再起航,我的学习笔记之JavaScript设计模式30(简单模板模式)
简单模板模式 概念介绍 简单模板模式(Simple template): 通过格式化字符串拼凑出视图避免创建视图时大量节点操作,优化内存开销. 创建模板 在实际的业务中如果我们需要进行前后台交互,或多 ...
- 再起航,我的学习笔记之JavaScript设计模式09(原型模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...
- 再起航,我的学习笔记之JavaScript设计模式05(简单工程模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...
随机推荐
- 用Nodejs 实现一个简单的 Redis客户端
目录 0. 写在前面 1. 背景映入 2. 数据库选择 3. Nodejs TCP连接 3. 代码编写 4. 实验 5. wireshark 抓包分析 6. 杂与代码 0. 写在前面 大家如果有去看过 ...
- TensorFlow深度学习!构建神经网络预测股票价格!⛵
作者:韩信子@ShowMeAI 深度学习实战系列:https://www.showmeai.tech/tutorials/42 TensorFlow 实战系列:https://www.showmeai ...
- HMM算法python实现
基础介绍,后5项为基础5元素 Q = ['q0', 'q1', 'q2', 'q3'] # 状态集合 States,共 N 种状态 V = ['v0', 'v1'] # 观测集合 Observatio ...
- KubeEdge快速上手与社区贡献实践
1.KubeEdge的架构特点与优势 持久化 云端组件,EdgeController,设备抽象API,CSI Driver,Admission WebHook 边缘组件,EdgeHub,MetaMan ...
- VM安装Centos7操作系统
个人名片: 对人间的热爱与歌颂,可抵岁月冗长 Github:念舒_C.ying CSDN主页️:念舒_C.ying 个人博客 :念舒_C.ying 视频教程:https://live.csdn.ne ...
- Go语言输出函数fmt.Print、fmt.Printf、fmt.Println的用法区别
fmt 包的介绍 fmt = format,是一种格式化输出函数汇总包,用于格式化输出 fmt.Print === 原样输出 Print formats using the default forma ...
- 关于咪咕视频的m3u8再次解析
软件和源码 前言 之前写过一片文章: 关于突破咪咕视频付费限制的研究, 但是后来我发现评论说已经不能用了,我知道肯定是api修改了,写这种东西就是这样,不一定什么时候就变化了,然后就用不了了,我懒得继 ...
- 深入理解 MySQL 的事务隔离级别和 MVCC 机制
前言 我们都知道 MySQL 实现了 SQL 标准中的四个隔离级别,但是具体是如何实现的可能还一知半解,本篇博客将会从代码层面讲解隔离级别的实现方式,下面进入正题. 事务 考虑这样一个场景:博主向硝子 ...
- VS2019发布至远程IIS部署流程
服务器部署 传统的开发将项目发布至本地桌面之后,复制至站点目录或通过FTP上传站点目录,有点小麻烦,通过开发工具VS2019本身集成的功能,可以一步到发布到远程IIS站点. 条件: VS系列发工具,例 ...
- 布尔值、元组、集合、input、格式化输出、赋值、运算符
今日内容总结 目录 今日内容总结 数据类型之布尔值bool 数据类型之元组tuple 数据类型之集合set 与用户交互 1.获取输入: input 2.输出内部信息 3.在python2中与pytho ...