C++ QT 在 class 结构中传递消息的最佳方式

C++ QT best way to pass a message higher in class structure

我目前正在实现一个程序,在QT中实现PC程序与外部设备的TCP通信。我遇到的问题比较笼统,但我会以这个为例。

我的 class 层次结构如下所示:

            Program
           /       \
      Server_A <--> Server_B <--- External system
          |
       Sockets[]
       /        \
  Commands      Confirmations
                /     |     \
         Interf1   Interf2    Interf3

我可以从设备 (Socket) 获取命令,我的命令进入 Confirmation class,实现任何 Interface 作业,并且 returns确认返回给 Socket,后者将其发送回设备。

当我想从外部系统发送命令时出现问题,我也必须确认。

  1. 我在 Server_B 上收到一条消息并将其传递给 Server_A,其中包含以下信息:socket 发送命令和命令实现。
  2. 我将命令传递给特定的 socket
  3. SocketCommands 发送命令,因为存在外部系统命令的逻辑。
  4. Commands 准备消息,运行逻辑,并(通过套接字)向设备发送消息
  5. Socket 等待响应
  6. Socket 获取响应,了解这是对外部系统命令的响应,并将其传递回 Commands
  7. Commands实现其逻辑。

到这里就可以了,但是下一步是:

  1. Commands需要向外部系统确认成功(或失败)。

所以基本上,我要做的就是通过这种方式将消息从 Commands 传递到 Server_BCommands->Socket->Server_A->Server_B。对于所有这些 classes,我将不得不创建一个不必要的方法来传递这个信息。有没有办法以某种方式解决这个问题?在我的编程过程中,经常发生我必须将某些东西传递到我的 class 结构的更高层,并且通过仅进一步传递信息的附加方法来实现它看起来是多余的。

我已经为这个问题提供了一个示例伪代码:

class Program
{
    ServerB serverB;
    ServerA serverA;
}

class ServerB
{
    void send(QString msg);
}

class ServerA
{
    QVector<MySocket*> sockets;
}

class MySocket
{
    Commands commands;
    Confirmations confirmations;
}

class Commands
{
    void doLogic();
    void sendToExternalSystem(QString message); //How to realize it?
}

我的程序要大得多,但我希望它能给你一个线索,告诉你我正在努力实现什么。最简单的解决方案是在 Sockets、Server_A 和 Server_B 中添加一个方法 void sendToExternalSystem(QString message),并在构造期间为每个父级提供一个指针(命令将可以访问套接字,套接字将具有访问 server_a,server_a 将访问 server_b)

最后,我想出了一个解决办法。有必要实施 ExternalCommand class,这些实例是在 Server_B.

中创建的

在极简解中,它有:1.字段QString Message,2.方法QString getMessage(),3.方法void finish(QString),4.信号void sendToExternal(QString)

当我在 Server_B 中读取从外部系统发送的消息时,我创建了这个 class 的实例,并将其连接到 Server_B 发送方法。在我的代码中,它看起来像这样:

ExternalCommand::ExternalCommand(QString message, QObject* parent) : QObject(parent)
{
    this->message=message;
}

QString ExternalCommand::getMessage()
{
    return this->message;
}

void finish(QString outputMessage)
{
    emit sendToExternal(outputMessage);
}
void Server_B::onReadyRead()
{
    QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
    QString message = socket->readAll();
    ExternalCommand* cmd = new ExternalCommand(message);
    connect(cmd, &ExternalCommand::sendToExternal, socket, 
        [socket](QString message) {socket->write(message.toUtf8());});
}

发送命令后,ExternalCommand 中也有必要实施某种类型的对象销毁,但这不是这个问题的重点。

所以一旦这个实现了,而不是消息QString,消息被传递到较低级别ExternalCommand*,一旦得到答案,就可以发送它通过调用 ExternalCommand::finish(QString outputMessage); 回到外部系统。当然,这只是这个问题的最小解决方案。

感谢@MatG 向我指出 Promise/Future 模式,这对找到这个解决方案很有帮助。