• Design patterns--策略模式


    设计模式策略模式

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

    • 代码示例
    #ifndef MODBUS_H
    #define MODBUS_H
    #include 
    
    std::string convertToHex(unsigned char* data, int length);
    
    class Modbus
    {
    public:
        Modbus();
        virtual void modbusFormat() = 0;
    };
    
    #endif // MODBUS_H
    
    #include "modbus.h"
    #include 
    #include 
    
    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(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()
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    #ifndef MODBUSRTU_H
    #define MODBUSRTU_H
    #include 
    #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());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    #ifndef MODBUSTCP_H
    #define MODBUSTCP_H
    #include 
    #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 
    
    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());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    #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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    #include 
    #include 
    #include 
    #include 
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    • 效果演示
      在这里插入图片描述
  • 相关阅读:
    信奥中的数学:集合与子集
    SpringBoot 如何进行参数校验?
    mini-imagenet数据集下载-阿里云网盘不限速下载
    IO流 - File - properties
    C++ STL进阶与补充(set/multiset容器)
    百度百家号旋转验证码识别研究
    作用域和作用域链
    总结CSS常用的知识点以及SCSS语法
    vscode 局域网访问HTML文件
    单词记忆系统二:音标字符输入(re从字符串中提取音标字符;依序打印音标字符;输入对应序号;替换序号。-> 完成“音标输入”)
  • 原文地址:https://blog.csdn.net/Love_XiaoQinEr/article/details/133801249