【问题标题】:Designing class for handling multiple communication protocols handling处理多种通信协议处理的设计类
【发布时间】:2020-05-18 13:54:55
【问题描述】:

我正在开发一个应处理多种通信协议(以太网、串行等)的 C++ 应用程序。每个通信协议都作为一个特定的类来处理。 为了尽可能少地公开有关上述类和协议的内部结构和组织的信息,我想以某种方式包装所有这些功能,并提供一些通用的 API,用于通过选定的协议发送数据。

基本上API应该提供什么(参数不限于此,是大意):

bool sendData(uint8_t* buffer, const size_t& bufferSize);

void receiveData(uint8_t* dataBuffer, size_t& bufferSize);

为上述功能创建通用 API 的最佳方式是什么,如果可能的话,还涉及一些设计模式?

问候。

【问题讨论】:

  • 这似乎是一个从抽象 class 继承的非常简单的用例。你试过吗?
  • @StephenNewell 好吧,是的,我一直在研究工厂设计模式,但我不能 100% 确定,通过该模式的设计和使用,这是否是正确的方式......

标签: c++ design-patterns server-communication


【解决方案1】:

为上述创建通用 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(即接口)一起使用,而不是直接与 EthernetCommunicationSerialCommunicationCarrierPigeon 等特定实现一起使用。因此,代码遵循"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;

【讨论】:

  • 这似乎是一个不错的方法。我认为每个实例需要有多个回调函数。编辑:是否可以添加两个类都不常见的功能?
  • @RobertŠandor 基于对象的方法比基于回调的方法更通用。后者通常在您仅封装行为时使用。
  • 我正是为了这个目的使用了这个模式,效果很好:public.msli.com/lcs/muscle/html/classmuscle_1_1DataIO.html
  • @RobertŠandor 您可以在不属于Communication 接口的具体实现中实现其他成员函数。但是,如果客户端代码通过(通用)接口与这个实现一起工作,它只能调用接口暴露的成员函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 2011-01-30
  • 2010-09-09
  • 2016-11-03
  • 2012-04-30
  • 2015-12-09
  • 2016-05-22
相关资源
最近更新 更多