【问题标题】:C++ Design Pattern for a Messaging System?消息系统的 C++ 设计模式?
【发布时间】:2009-04-25 20:45:10
【问题描述】:

我的任务是实现一个用于实时模拟的消息传递系统。该系统中需要存在多种不同类型的消息传递对象,将来可能会添加更多。这些对象代表了 sim 中玩家之间的主要通信方式。假设我完全理解我的要求,消息传递对象可以由以下属性定义:

  • 发送协议(玩家可以发送什么消息以及何时发送)
  • 接收协议(玩家可以接收哪些消息以及接收频率)
  • 消息格式(发送数据的结构)

仿真代码目前只支持一种收发协议和一种消息格式。我的工作是使代码更具可扩展性,以便它可以支持未来对协议和消息结构的更改/添加。对此的第一种方法是为每个属性定义抽象基类,并让每个消息传递对象由它们的句柄组成。然后可以将每个消息传递对象编写为协议和格式对象的不同组合。我担心这种设计会很快变得过于笼统,从而成为维护的噩梦。一想到要筛选十几个文件来弄清楚 FooMessaging 到底是如何工作的,我就感到畏缩。

我将用 C++ 编写这个,但我认为这实际上是一个更一般的设计问题。我可以在这里应用任何“标准”模式或最佳实践吗?

【问题讨论】:

    标签: c++ language-agnostic design-patterns


    【解决方案1】:

    好的,我怀疑您正在从大约 G 开始进行 A 到 Z 过程。

    首先,您的用例是什么?你想做什么?您正在构建什么样的“消息系统”?电子邮件?我是?心灵感应?

    其次,您从这些用例中获得的领域是什么?

    现在,考虑到这一点,是的,您经常发现为基础课程制作 ABC 很方便。考虑改为创建一个接口(尽管 C++ 中接口和 ABC 之间的区别没有其他语言那么明确。)在过去的 20 年中,基于继承的 OO 已经证明会带来很多问题,因此接口和聚合是现在受到青睐。不是总是更好,但你应该首先想到它们。

    现在,告诉我与“协议”相对应的物理事物是什么?您的意思是建模消息流之类的东西吗?它是一种传播媒介吗?

    特别是格式听起来很可疑,如果不是立即错误的话:消息格式往往与协议密切相关。

    基本上,先备份一下,然后告诉我们更多关于您尝试做什么的信息。

    更新

    啊哈。好吧,看,我们从中得到了很多帮助。首先,您指的是可用操作意义上的“协议”——一种完全合理的用法,但是当您将它与 TCP 与 UDP 混淆时会混淆,就像我所做的那样。

    现在,也就是说,您确实至少有几个选择。在下文中,我使用术语“玩家”来表示 sim 中可以发送或接收消息的任何实体。

    这里的关键概念是围绕变化的轨迹和非功能性需求进行设计。明显的变化轨迹是

    • 你可以有几个“协议”,如果你有多达三个,你应该计划总是有更多。如果您期望两个以上,请计划您可以拥有任意多个。

    • 您可以使用多种不同的方式来格式化消息,例如 JSON、XML 或 YAML。再说一次,如果您期望超过两个,请计划您可以拥有任意多个。

    • 您可以有多种传输机制。从表面上看,你至少可以使用 UNIX 域套接字×共享内存×命名管道,但是我的直觉说你也可以选择本地和远程,也就是说你也可以选择 UDP 或 TCP。肯定不止两个,规划可扩展性。

    选项1:

    使用代理模式,其中每个协议都定义了一个接口,该接口必须以多种方式之一实现,具体取决于底层的消息传递格式。玩家宣传他们愿意接收的信息;在他们准备接收消息时,他们构造了一些东西,为他们收到的任何特定操作消息调用他们的代码。为了发送,他们构建了一个对象,为他们的接收伙伴 Player 实现了适当的接口。

    在幕后,这些对象可以有多种实现,每种实现不同的消息格式和传输机制。

    这样的系统示例包括 SOM/DSOM a/k/a CORBA 和使用远程接口的 Java RMI。

    选项 2:

    您可以围绕命令模式构建一些东西。每个协议都有一个特定的“发送我”的实现,你的接收者只知道如何重建一个发送的对象。命令对象有一个混合(多重继承,或在运行时作为对象传递),它知道如何编组和序列化命令对象;您可以拥有第二个了解传输机制的人。

    您通过序列化对象并使用您的传输机制将序列化的表单移动到接收方,从而在特定协议上发送消息。接收方“重新水化”对象,并根据发送的实际类型调用适当的方法。

    这方面的一个例子是使用 Serializable 接口而不是使用 Remote 的 Java RMI。

    【讨论】:

    • 我已经改写了我的问题,希望能更清楚。我不是设计消息系统本身。相反,我正在寻找一种好方法,以便将来轻松添加新的发送/接收协议和消息格式。是的,在我们的例子中,消息格式确实与所使用的协议无关。抱歉含糊其辞,但我不能提供具体细节。
    • 这个问题还是很模糊的。我参与了许多项目,其中包括可以符合您描述的内容,它们都非常不同。这告诉我,您对问题的描述仍然不够具体,无法让任何人给您有用的答案。会从根本上改变您的设计但您尚未讨论的事情是消息是在同一台机器上运行的进程之间、网络上、线程之间还是在单个线程中发送的。任何对象是否可以向任何其他对象发送消息,或者是否期望对象执行特定的操作
    • 为了接收消息。消息循环会是可接受的设计吗?消息传递层是否应该调用对象上的方法来响应消息?这甚至可以接受吗?消息是同步的还是异步的?有保证交货吗?消息传递层是否期望存储消息并将消息转发到尚不存在、未侦听或无法访问的对象?有人提出 Apache ActiveMQ 作为答案这一事实应该告诉您您的问题有多糟糕。
    • 传输层对于这个项目来说已经是一成不变的,从我的角度来看,它可以有效地被视为一个黑盒子。此外,玩家可以随时尝试发送消息,但发送协议将保留它们,直到它们被允许离开。同样,玩家将在每一帧物理上接收消息,但接收协议不会让它们在正确的时间被处理。
    【解决方案2】:

    我相信你应该看看Apache ActiveMQ。实际上,它是用 Java 编写的,但可以选择使用 C++ 客户端,而且文档也很好。

    干杯。

    【讨论】:

    • 如果没有警告人们不要使用 ActiveMQ,我看不到这一点。
    • 为什么不呢?请给出意见。谢谢。
    • 我在一个项目中看到过它。它未能扩展到中等数量的客户端,并且存在从未解决的严重稳定性问题。雪上加霜的是,它的表现相当糟糕。在我看来,它是一个可笑的过度设计的解决方案,它不需要一个过度概括到这种程度的解决方案。
    猜你喜欢
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 2016-04-24
    • 1970-01-01
    • 2015-06-22
    相关资源
    最近更新 更多