设计class 用于处理多种通信协议处理
Designing class for handling multiple communication protocols handling
我正在开发一个应该处理多种通信协议(以太网、串行等)的 C++ 应用程序。每个通信协议都作为特定的 class 处理。
为了尽可能少地公开有关上述 classes 和协议的内部结构和组织的信息,我想以某种方式包装所有这些功能并提供一些通用的 API 用于发送数据选定的协议。
基本上API应该提供什么(参数不限于此,但是是大意):
bool sendData(uint8_t* buffer, const size_t& bufferSize);
void receiveData(uint8_t* dataBuffer, size_t& bufferSize);
为上述功能创建通用 API 的最佳方法是什么,如果可能的话涉及一些设计模式?
此致。
What is the best way to create a generic API for the said
functionality, and if possible involve some design pattern?
The Strategy Pattern 看起来适合这种情况。
首先,为所有不同的通信策略定义一个接口,Communication
:
class Communication {
public:
virtual ~CommunicationStrategy() = default;
virtual bool sendData(uint8_t* buffer, const size_t& bufferSize) = 0;
virtual void receiveData(uint8_t* dataBuffer, size_t& bufferSize) = 0;
};
然后,您的具体实现——即策略——应该派生自这个接口:
class EthernetCommunication: public Communication {
public:
// ...
bool sendData(uint8_t*, const size_t&) override;
void receiveData(uint8_t*, size_t&) override;
};
class SerialCommunication: public Communication {
public:
// ...
bool sendData(uint8_t*, const size_t&) override;
void receiveData(uint8_t*, size_t&) override;
};
class CarrierPigeon: public Communication {
public:
// ...
bool sendData(uint8_t*, const size_t&) override;
void receiveData(uint8_t*, size_t&) override;
};
客户端代码将与(指向)Communication
(即接口)一起工作,而不是直接与特定实现(如 EthernetCommunication
、SerialCommunication
或 CarrierPigeon
。因此,代码遵循 "program to an interface, not to an implementation" 建议。例如,你可能有一个像这样的工厂函数:
std::unique_ptr<Communication> CreateCommunication();
此工厂函数 return 是上述策略之一。 return 的策略可以在 运行 时确定。
std::unique_ptr<Communication> com = CreateCommunication();
// send data regardless of a particular communication strategy
com->sendData(buffer, bufferSize);
这样,上面的代码就不会耦合到任何特定的实现,而只会耦合到接口 Communication
,它对所有不同的可能通信策略都是通用的。
如果不同的通信策略不需要每个实例的数据,只需要两个回调而不是一个对象就可以了:
using data_sender_t = bool (*)(uint8_t*, const size_t&);
using data_receiver_t = void (*)(uint8_t*, size_t&);
// set these function pointers to the strategy to use
data_sender_t data_sender;
data_receiver_t data_receiver;
我正在开发一个应该处理多种通信协议(以太网、串行等)的 C++ 应用程序。每个通信协议都作为特定的 class 处理。 为了尽可能少地公开有关上述 classes 和协议的内部结构和组织的信息,我想以某种方式包装所有这些功能并提供一些通用的 API 用于发送数据选定的协议。
基本上API应该提供什么(参数不限于此,但是是大意):
bool sendData(uint8_t* buffer, const size_t& bufferSize);
void receiveData(uint8_t* dataBuffer, size_t& bufferSize);
为上述功能创建通用 API 的最佳方法是什么,如果可能的话涉及一些设计模式?
此致。
What is the best way to create a generic API for the said functionality, and if possible involve some design pattern?
The Strategy Pattern 看起来适合这种情况。
首先,为所有不同的通信策略定义一个接口,Communication
:
class Communication {
public:
virtual ~CommunicationStrategy() = default;
virtual bool sendData(uint8_t* buffer, const size_t& bufferSize) = 0;
virtual void receiveData(uint8_t* dataBuffer, size_t& bufferSize) = 0;
};
然后,您的具体实现——即策略——应该派生自这个接口:
class EthernetCommunication: public Communication {
public:
// ...
bool sendData(uint8_t*, const size_t&) override;
void receiveData(uint8_t*, size_t&) override;
};
class SerialCommunication: public Communication {
public:
// ...
bool sendData(uint8_t*, const size_t&) override;
void receiveData(uint8_t*, size_t&) override;
};
class CarrierPigeon: public Communication {
public:
// ...
bool sendData(uint8_t*, const size_t&) override;
void receiveData(uint8_t*, size_t&) override;
};
客户端代码将与(指向)Communication
(即接口)一起工作,而不是直接与特定实现(如 EthernetCommunication
、SerialCommunication
或 CarrierPigeon
。因此,代码遵循 "program to an interface, not to an implementation" 建议。例如,你可能有一个像这样的工厂函数:
std::unique_ptr<Communication> CreateCommunication();
此工厂函数 return 是上述策略之一。 return 的策略可以在 运行 时确定。
std::unique_ptr<Communication> com = CreateCommunication();
// send data regardless of a particular communication strategy
com->sendData(buffer, bufferSize);
这样,上面的代码就不会耦合到任何特定的实现,而只会耦合到接口 Communication
,它对所有不同的可能通信策略都是通用的。
如果不同的通信策略不需要每个实例的数据,只需要两个回调而不是一个对象就可以了:
using data_sender_t = bool (*)(uint8_t*, const size_t&);
using data_receiver_t = void (*)(uint8_t*, size_t&);
// set these function pointers to the strategy to use
data_sender_t data_sender;
data_receiver_t data_receiver;