C++设计中,如何用对象表示协议的不同阶段

C++ design, how to represent different stages of a protocol with objects

本文关键字:协议 表示 对象 何用 C++      更新时间:2023-10-16

这不是一个技术问题,而是一个 C++ 设计问题。

通常,我似乎必须设计程序来管理一些具有某种连接,解析阶段和抽象视图的协议。通常,我尝试在设计程序时将关注点分离放在首位。

我一直以对象的"堆栈"结尾,一个系统位于解析器之上,而解析器又位于连接之上(通常有更多层)。然后,这些对象使用成员函数调用来调用其下方的层(Tx),并使用回调(通常std::function)来捕获来自其他方向(Rx)的信息。

这种设计看起来真的很差,因为它增加了复杂性,并且每一层都必须有一个逐渐更大的构造函数等等。另外,由于连接通常使用类似ASIO的东西,因此回调通常位于不同的线程上,因此很难推断线程安全性。

是否有一个设计术语或成语可以更好地代表这种结构/功能?

编辑

一个简单的例子

class basic_connection {
basic_connection(std::string address);
void send(std::string);
std::function<void(std::string)> on_receive;
};

我有几个这样的类,它们保存该层的状态,并通过它们的公共成员函数和回调粘合在一起。

此之上的层接收网络的命令数据处理并调用basic_connection::send。并从basic_connection中获取原始数据,并将其转换为未经处理的上层的命令。

编辑2:

我忘了提到的另一个问题是,您最终通过堆栈转发了一些接口,例如,顶层仍然需要知道连接状态。

如果没有一套要求,很难推荐任何东西。但是,从您问题中的高级描述来看,您可能希望使用模型-视图-控制器模式,可能与其他模式结合使用。请记住,设计模式是你的朋友,你是决定使用是否合适以及在多大程度上合适的人。设计模式很容易被滥用,而且这种情况一直在发生。

听起来您要做的是通常所说的"构建管道"。

以下是连接两层的一种简单方法:

class I
{
virtual void a() = 0;
virtual void b() = 0;
}
class X
{
I& m_i;
X(I& i) : m_i(i) {}
void onRecv(const char* data, size_t len)
{
for (size_t p = 0; p < len; p++)
switch (data[p])
{
case 'a': m_i.a(); break;
case 'b': m_i.b(); break;
}
}
}
class Y : public I
{
void a() { ... }
void b() { ... }
}
int main()
{
X x;
Y y(x);
while (...)
x.onRecv(data,len);
}

在我看来,你需要的是额外的抽象。我将首先设计一个通用类型来描述层的实际含义,并(如果适用)针对每个特定层进行细化,而不考虑这些层的具体协议。 因此,您可以说 layer-k 协议需要一个 layer-(k-1) 类型的对象。

从您的描述中,我假设您的较高层正在构造其直接的较低层,这使得构造函数膨胀。只需请求构造函数中下一个较低层的引用(可能最好由shared_ptrunique_ptr实现),并让接口用户为其实例化而烦恼。
由于您定义了抽象接口,因此您仍然可以多态地使用下层,而不必为它的实现方式和使用特定的下层协议而烦恼。

对于接收,通常需要可以以相同方式实现的回调。您甚至可以将它们安装在更高层对象的构造函数中,并在析构函数中删除它们。


如果您在设计时知道哪个协议将与哪个其他协议一起使用,您还可以通过使协议实现成为接收其较低协议的模板来替换多态调用,如下所示:Tcp<Ip<Ethernet<Device>>>.