Design patterns--策略模式

设计模式之策略模式

笔者经常使用Modbus TCP和Modbus RTU通信协议,而两种的请求数据的格式不一样,故而采用策略模式来健壮整个工程项目。

  • 代码示例
#ifndef MODBUS_H
#define MODBUS_H
#include <string>std::string convertToHex(unsigned char* data, int length);class Modbus
{
public:Modbus();virtual void modbusFormat() = 0;
};#endif // MODBUS_H#include "modbus.h"
#include <sstream>
#include <iomanip>std::string convertToHex(unsigned char* data, int length)
{// std::string hexString;// for (int i = 0; i < length; i++)// {//     hexString += (i > 0 ? " " : "") + std::to_string(data[i]);// }// return hexString;// std::stringstream ss;// ss << std::hex << std::setfill('0');// for (int i = 0; i < length; i++) {//     ss << std::setw(2) << static_cast<int>(data[i]) << " ";// }// return ss.str();std::stringstream ss;ss << std::hex << std::setfill('0') << std::uppercase;for (int i = 0; i < length; i++) {ss << std::setw(2) << static_cast<int>(data[i]);if (i < length - 1) {ss << " ";}}return ss.str();
}Modbus::Modbus()
{}
#ifndef MODBUSRTU_H
#define MODBUSRTU_H
#include <stdint.h>
#include "modbus.h"class ModbusRtu : public Modbus
{
public:ModbusRtu();void modbusFormat() override;void transmitRTU();private:uint8_t m_slaveId;uint8_t m_funCode;uint16_t m_registerBeginAddr;uint16_t m_registerTotal;uint16_t m_crc;unsigned char transmitData[8];
};#endif // MODBUSRTU_H#include "modbusrtu.h"// 计算CRC16校验值
static uint16_t calculateCRC16(uint8_t* data, uint16_t length)
{uint16_t crc = 0xFFFF;for (uint16_t i = 0; i < length; i++) {crc ^= data[i];for (uint8_t j = 0; j < 8; j++) {if (crc & 0x0001) {crc >>= 1;crc ^= 0xA001;} else {crc >>= 1;}}}return crc;
}ModbusRtu::ModbusRtu()
{m_slaveId = 1;m_funCode = 3;m_registerBeginAddr = 10;m_registerTotal = 50;
}void ModbusRtu::modbusFormat()
{transmitData[0] = m_slaveId;transmitData[1] = m_funCode;transmitData[2] = m_registerBeginAddr >> 8;transmitData[3] = m_registerBeginAddr & 0xFF;transmitData[4] = m_registerTotal >> 8;transmitData[5] = m_registerTotal & 0xFF;m_crc = calculateCRC16(transmitData, 6);transmitData[6] = m_crc >> 8;transmitData[7] = m_crc & 0xFF;transmitRTU();
}void ModbusRtu::transmitRTU()
{printf("[%s:%d][RTU] %s\n", __FILE__, __LINE__, convertToHex(transmitData, 8).c_str());
}
#ifndef MODBUSTCP_H
#define MODBUSTCP_H
#include <stdint.h>
#include "modbus.h"class ModbusTcp : public Modbus
{
public:ModbusTcp();void modbusFormat() override;void transmitTCP();private:uint16_t m_transactionIdentifier; //事务标识符号uint16_t m_protocolIdentifier; //协议标识符uint16_t m_dataLength; // 数据长度uint8_t m_slaveId;uint8_t m_funCode;uint16_t m_registerBeginAddr;uint16_t m_registerTotal;unsigned char transmitData[12];
};#endif // MODBUSTCP_H#include "modbustcp.h"
#include <stdio.h>static uint16_t numFlag = 0;ModbusTcp::ModbusTcp()
{m_slaveId = 0x01;m_funCode = 0x03;
}void ModbusTcp::modbusFormat()
{m_transactionIdentifier = numFlag;m_protocolIdentifier = 0;m_dataLength = 0x06;m_registerBeginAddr = 0x0A;m_registerTotal = 0x32;transmitData[0] = m_transactionIdentifier >> 8;transmitData[1] = m_transactionIdentifier & 0xFF;transmitData[2] = m_protocolIdentifier >> 8;transmitData[3] = m_protocolIdentifier & 0xFF;transmitData[4] = m_dataLength >> 8;transmitData[5] = m_dataLength & 0xFF;transmitData[6] = m_slaveId;transmitData[7] = m_funCode;transmitData[8] = m_registerBeginAddr >> 8;transmitData[9] = m_registerBeginAddr & 0xFF;transmitData[10] = m_registerTotal >> 8;transmitData[11] = m_registerTotal & 0xFF;numFlag++;transmitTCP();
}void ModbusTcp::transmitTCP()
{printf("[%s:%d][TCP] %s\n", __FILE__, __LINE__, convertToHex(transmitData, 12).c_str());
}
#ifndef COMMPROTOCOL_H
#define COMMPROTOCOL_H
#include "modbus.h"class CommProtocol
{
public:enum e_Modbus{ModbusTCP = 1,ModbusRTU};public:CommProtocol();void setModbus(Modbus* mbus);void requestData();private:Modbus* m_Modbus;
};#endif // COMMPROTOCOL_H#include "commprotocol.h"CommProtocol::CommProtocol()
{}void CommProtocol::setModbus(Modbus *mbus)
{m_Modbus = mbus;
}void CommProtocol::requestData()
{m_Modbus->modbusFormat();
}
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <ctime>
#include "modbustcp.h"
#include "modbusrtu.h"
#include "commprotocol.h"using namespace std;int main()
{ModbusTcp modTcp;ModbusRtu modRtu;CommProtocol commProtocol;// 设置随机数种子std::srand(std::time(0));while (true) {// 生成1和3之间的随机数int randomNumber = std::rand() % 3 + 1;// printf("randomNumber = %d\n", randomNumber);if(randomNumber == CommProtocol::e_Modbus::ModbusTCP){commProtocol.setModbus(&modTcp);commProtocol.requestData();}else if(randomNumber == CommProtocol::e_Modbus::ModbusRTU){commProtocol.setModbus(&modRtu);commProtocol.requestData();}else{commProtocol.setModbus(&modTcp);commProtocol.requestData();}sleep(2);}cout << "==Over==" << endl;return 0;
}

  • 效果演示
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/103330.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[GAMES101]透视投影变换矩阵中为什么需要改变z值

一、问题提出 在GAMES101-Lecture4 Transformation Matrices 一节中&#xff0c;闫老师介绍了正交投影和透视投影。 在讲透视投影变换矩阵 M p e r s p → o r t h o M_{persp→ortho} Mpersp→ortho​时&#xff0c;同学们对矩阵中的z分量是变化的还是不变的有很多争论。即下…

数据一致性分发

为什么要数据分发 微服务中&#xff0c;每个服务都有独立的数据源&#xff0c;这使得数据同步成为难题。 拉模式or推模式&#xff1f; 拉模式存在的问题 由于网络延迟&#xff0c;拉取的数据不一定是最新的 如果频繁向另一服务拉取数据&#xff0c;会给服务造成压力&#xf…

保护敏感数据的艺术:数据安全指南

多年来&#xff0c;工程和技术迅速转型&#xff0c;生成和处理了大量需要保护的数据&#xff0c;因为网络攻击和违规的风险很高。为了保护企业数据&#xff0c;组织必须采取主动的数据安全方法&#xff0c;了解保护数据的最佳实践&#xff0c;并使用必要的工具和平台来实现数据…

大模型时代的开发者:从飞桨PPDE到文心布道师

飞桨开发者技术专家&#xff08;PPDE&#xff09;谢杰航研究方向为AI城市规划、景观设计、生态环境及农业等领域的应用落地。他在此前Wave Summit 2023深度学习开发者大会上为大家带来了主题为《大模型时代的开发者&#xff1a;从飞桨PPDE到文心布道师》的演讲。本次演讲共分为…

解决MySQL错误-this is incompatible with sql_mode=only_full_group_by

报错 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘数据库名.表名.字段名’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_modeonly_full_group_by 原因 MySQL错误-t…

Java架构师缓存性能优化

目录 1 缓存的负载策略2 缓存的序列化问题3 缓存命中率低4 缓存对数据库高并发访问5 缓存数据刷新的策略5.1. 实时策略5.2. 异步策略5.3. 定时策略6 何时写缓存7 批量数据来更新缓存8 缓存数据过期的策略9 缓存数据如何恢复10 缓存数据如何迁移11 缓存冷启动和缓存预热1 缓存的…

全新整合热搜榜单热门榜单内容系统聚合源码/带教程安装

源码简介&#xff1a; 在移动互联网时代&#xff0c;我们每天都会接收到大量的信息&#xff0c;但是想要知道哪些是最热门的话题和内容&#xff0c;往往需要花费很多精力去搜索和筛选。因为有这个需要&#xff0c;一个全新整合热搜榜单热门榜单内容系统聚合源码就应运而生了&a…

PMP证书有什么用?考试条件是什么?

PMP证书摆在明面上的一个用处就是在招聘项目经理岗或者PMO岗的岗位要求中都会有一条&#xff1a;持有PMP证书优先。面试的时候&#xff0c;如果两个候选人的经历、经验、期望薪资都差不多&#xff0c;那么HR就会更倾向于有PMP/ACP等证书的候选人。 PMP是什么&#xff1f; PMP是…

LabVIEW将视觉生成器AI用作OPC服务器

LabVIEW将视觉生成器AI用作OPC服务器 介绍如何将视觉生成器AI配置为OPC服务器&#xff0c;并使用共享变量共享视觉生成器AI生成的结果。OPC是一系列标准规范&#xff0c;定义了来自不同制造商的控制设备之间的实时数据通信。OPC数据访问通信是基于客户端服务器的通信。 共享系…

whistle安卓手机抓包(图文详解)

1、安装node https://nodejs.org &#xff08;官网下载对应的node,一般推荐长期稳定版本 LTS&#xff09; 需要node的版本是大于 v0.10.0 查看自己本地node 版本号 node -v2、安装whistle npm i -g whistle3、开启whistle 补充说明&#xff1a; ● w2 stop&#xff1a;关闭…

XML是不是主要用做配置文件?

2023年10月11日&#xff0c;周三下午 这几天发现tomcat的配置文件主要是用XML文件来写的&#xff0c; 于是就有了这个问题。 是的,XML非常适合用来做配置文件。 XML作为配置文件的主要优点: 可读性强。XML使用标签结构组织数据,内容清晰易懂。跨语言和跨平台。XML作为纯文本…

Servlet的部署与安全

1 Servlet 部署 Servlet规范关于各个东西该放在哪里有许多严格的规则。 1.1 WAR war文件代表Web归档(Web Archive)&#xff0c;war实际就是一个JAR&#xff0c;只不过扩展名是.war而不是.jar。 其采用了一种可移植的压缩形式&#xff0c;把整个Web应用结构&#xff08;去掉…

相似与不同:数字孪生和元宇宙的对比

数字孪生和元宇宙是两个备受瞩目的概念&#xff0c;都在数字领域产生了巨大的影响。它们有一些相似之处&#xff0c;但也存在显著的不同。本文将介绍它们的相同点和不同点&#xff0c;以及它们在不同应用领域的前景。 1. 相同点 虚拟性质&#xff1a; 数字孪生和元宇宙都是虚…

Linux引导故障排除:从问题到解决方案的详细指南

1 BIOS初始化 通电->对硬件检测->初始化硬件时钟 2 磁盘引导及其修复 2.1 磁盘引导故障 磁盘主引导记录&#xff08;MBR&#xff09;是在0磁道1扇区位置&#xff0c;446字节。 MBR作用&#xff1a;记录grub2引导文件的位置 2.2 修复 步骤&#xff1a;1、光盘进…

1014蓝桥算法双周赛,学习算法技巧,助力蓝桥杯

家人们&#xff0c;我来免费给大家送福利了&#xff01;&#xff01;&#xff01; 【1014蓝桥算法双周赛 】 背景 蓝桥杯全国软件和信息技术专业人才大赛是由工业和信息化部人才交流中心举办的全国性IT学科赛事。参赛高校超过1200余所&#xff0c;累计参赛人数超过40万人。该…

PHP 员工工资管理系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 员工工资管理系统是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 php员工工资管理系统 代码 https://download.csdn.net/download/qq_41221322/884215…

用手势识别来测试视力?试试用百度AI来实现想法

文章目录 ⭐ 前言⭐ 灵感来源⭐ 项目准备⭐ 项目实现⭐ 不足与展望 ⭐ 前言 10月17日&#xff0c;以“生成未来&#xff08;PROMPT THE WORLD&#xff09;”为主题的百度世界2023将在北京首钢园举办。百度创始人、董事长兼首席执行官李彦宏将带来以“手把手教你做AI原生应用”…

【安全】linux audit审计使用入门

文章目录 1 audit简介2 auditctl的使用2 audit配置和规则3 工作原理4 audit接口调用4.1 获取和修改配置4.2 获取和修改规则4.3 获取审计日志 5 audit存在的问题5.1 内核版本5.2 审计日志过多造成的缓存队列和磁盘问题5.2 容器环境下同一个命令的日志存在差异 6 参考文档 1 audi…

睿趣科技:未来抖音开网店还有前景吗

随着科技的快速发展&#xff0c;电商平台已经成为了人们生活中不可或缺的一部分。在中国&#xff0c;抖音作为一个短视频平台&#xff0c;近年来迅速崛起&#xff0c;吸引了大量的用户和商家。那么&#xff0c;在未来&#xff0c;抖音是否还能为商家提供一个有效的电商平台呢?…

1688关键字搜索接口

1688关键字搜索接口&#xff0c;即item_search接口&#xff0c;是一个通过API接口进行程序操作的工具。它通过将买家在前端页面输入的关键字转化为后端服务器能够识别的格式&#xff0c;从而实现对指定关键字进行搜索&#xff0c;并返回相关结果。使用该API不仅可以省去繁琐的手…