为上述创建通用 API 的最佳方法是什么
功能,是否可能涉及一些设计模式?
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();
此工厂函数返回上述策略之一。可以在运行时确定返回哪个策略。
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;