13

这不是一个技术问题,而是一个 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:

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

4

3 回答 3

1

听起来您正在尝试做的就是通常所说的“构建管道”。

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

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);
}
于 2012-11-04T18:11:36.783 回答
1

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

于 2012-11-04T16:49:05.200 回答
0

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

根据您的描述,我假设您的较高层正在构建它们的直接较低层,这使得构造函数膨胀。只需为构造函数中的下一个较低层请求一个引用(可能最好由 a shared_ptror实现unique_ptr),并让接口用户为它的实例化而烦恼。
由于您定义了一个抽象接口,您仍然可以多态地使用下层,而不必担心它是如何实现的以及使用什么特定的下层协议。

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


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

于 2012-11-04T17:03:47.983 回答