简体   繁体   English

消息系统的C ++设计模式?

[英]C++ Design Pattern for a Messaging System?

I'm tasked with implementing a messaging system for a real-time simulation. 我的任务是实现用于实时模拟的消息传递系统。 There are several different kinds of messaging objects that need to exist in this system, and more might be added in the future. 此系统中需要存在多种不同类型的消息传递对象,并且将来可能会添加更多消息传递对象。 These objects represent the primary means of communication between the players in the sim. 这些对象代表了sim中玩家之间的主要通信方式。 Assuming I fully understand my requirements, the messaging objects can be defined by the following attributes: 假设我完全理解我的要求,可以通过以下属性定义消息传递对象:

  • Send protocol (what messages a player can send and when) 发送协议(播放器可以发送什么消息以及何时发送)
  • Receive protocol (what messages a player can receive and how often) 接收协议(播放器可以接收的消息和频率)
  • Message format (structure of the data being sent) 消息格式(正在发送的数据的结构)

The simulation code currently only supports one send and receive protocol and one message format. 模拟代码目前仅支持一种发送和接收协议以及一种消息格式。 My job is to make the code more extensible so it can support future changes/additions to protocols and message structure. 我的工作是使代码更具可扩展性,以便它可以支持将来对协议和消息结构的更改/添加。 A first-cut approach to this would be to define abstract base classes for each of the attributes and have each messaging object be composed of handles to them. 对此的第一个方法是为每个属性定义抽象基类,并让每个消息传递对象由它们的句柄组成。 Every messaging object can then be written as different combinations of protocol and format objects. 然后可以将每个消息传递对象写为协议和格式对象的不同组合。 My concern is that this design can quickly become over-generalized and thus a maintenance nightmare. 我担心的是,这种设计很快就会过度概括,从而成为维护的噩梦。 I cringe at the thought of sifting through a dozen files just to figure out how the heck a FooMessaging really works. 我想通过筛选十几个文件,只是为了弄清楚FooMessaging真正起作用。

I'll be writing this in C++, but I think this is really more a general design question. 我将用C ++编写这个,但我认为这更像是一个通用的设计问题。 Are there any "standard" patterns or best practices I can apply here? 我可以在这里申请任何“标准”模式或最佳实践吗?

Okay, I suspect you're doing an A to Z process starting at about G. 好的,我怀疑你正在从大约G开始进行A到Z的过程。

First of all, what are your use cases? 首先,你的用例是什么? What are you trying to do? 你想做什么? What kind of "messaging system" are you building? 您正在构建什么样的“消息系统”? EMAIL? 电子邮件? IM? IM? Telepathic? 心灵感应?

Second, what is the domain that you get from those use cases? 其次,您从这些用例中获得的域名是什么?

Now, having thought that through, then yes, you often find it convenient to make an ABC for the basic classes. 现在,考虑过,然后是的,你经常发现为基础课制作ABC很方便。 Consider making an interface instead (although the distinction between interfaces and ABCs in C++ is less well defined than other languages.) Over the last 20 years, inheritance-based OO has turned out to impose a lot of problems, so that interfaces and aggregation are now favored. 考虑改为创建一个接口(尽管C ++中的接口和ABCs之间的区别比其他语言定义的要差。)在过去的20年中,基于继承的OO已经证明存在很多问题,因此接口和聚合都是现在很受欢迎。 Not always better, but you should think of them first. 并不总是更好,但你应该先考虑它们。

Now, tell me what the physical thing corresponding to the "protocol" is? 现在,告诉我“协议”对应的物理内容是什么? Do you mean to model something like a message stream? 你的意思是建模消息流吗? Is it a communications medium? 它是一种通讯媒介吗?

Format in particular sounds suspicious, if not immediately wrong: message formats tend to be tied intimately to the protocol. 特别是格式听起来很可疑,如果不是立即错误的话:消息格式往往与协议密切相关。

Basically, back up a bit and tell us more about what you're trying to do , first. 基本上,先备份一下,然后告诉我们更多关于你要做的事情

Update 更新

Aha. 啊哈。 Okay, see, we get a lot of help from this. 好的,看,我们从中得到了很多帮助。 First, you mean "protocol" in the sense of the available operations — a perfectly reasonable usage, but confusing when you confound it with TCP vs UDP, that sort of thing, as I did. 首先,你指的是可用操作意义上的“协议” - 一个完全合理的用法,但是当你把它与TCP和UDP混淆时会让人感到困惑,就像我做的那样。

Now, that said, you do indeed have a couple of options at least. 现在,那说,你确实至少有几个选择。 In the following, I use the term "Player" for any entity in the sim that can send or receive messages. 在下文中,我对SIM中可以发送或接收消息的任何实体使用术语“播放器”。

The key notion here is to design around the loci for change, and around nonfunctional requirements. 这里的关键概念是围绕基因座进行设计以进行更改,并围绕非功能性需求进行设计。 The obvious loci of change are 明显的变化轨迹是

  • you can have several "protocols" in your sense, and if you have as many as three, you should just plan that there can always be more. 你可以在你的意义上有几个“协议”,如果你有多达三个,你应该计划总有更多。 If you expect more than two, plan that you can have arbitrarily many. 如果您期望超过两个,请计划您可以任意多次。

  • you can have several different ways of formatting messages, ie, JSON, XML, or YAML, say. 你可以有几种不同的格式化消息的方式,比如JSON,XML或YAML。 AGain, if you expect more than two, plan that you can have arbitrarily many. 如果你期望超过两个,那么AGain计划你可以任意多。

  • You can have several transport mechanisms. 您可以拥有多种传输机制。 From the sounds of things, you can at least use UNIX-domain sockets×shared memory×named pipes, but then my intuition says you also have the option of local and remote, which means you also have the option of UDP or TCP. 从事物的声音来看,你至少可以使用UNIX域套接字×共享内存×命名管道,但是我的直觉说你也可以选择本地和远程,这意味着你也可以选择UDP或TCP。 Definitely more than two, plan for extensibility. 绝对超过两个,计划可扩展性。

Option 1: 选项1:

Use a Proxy pattern, where each protocol defines an interface that must be implemented in one of several ways, depending upon the messaging format underneath. 使用代理模式,其中每个协议定义一个必须以多种方式之一实现的接口,具体取决于下面的消息传递格式。 Players advertise what messages they're willing to receive; 玩家宣传他们愿意收到的消息; at the time they are prepared to receive a message, they construct something that invokes their code for any specific operation message they receive. 在他们准备接收消息时,他们构造一些东西,为他们收到的任何特定操作消息调用他们的代码。 To send, they construct an object implementing the appropriate interface for their receiving partner Player. 要发送,他们构造一个对象,为其接收伙伴Player实现适当的接口。

Under the covers, these objects can have several realizations, each for a different messaging format and transport mechanism. 在幕后,这些对象可以有多个实现,每个实现用于不同的消息传递格式和传输机制。

Examples of a system like this include SOM/DSOM a/k/a CORBA, and Java RMI using the Remote interface. 像这样的系统的示例包括SOM / DSOM a / k / a CORBA和使用Remote接口的Java RMI。

Option 2: 选项2:

You can build something around the Command pattern. 您可以围绕Command模式构建一些东西。 Each protocol has a specific implementation of "send me", and your receiver simply knows how to reconstruct an object sent. 每个协议都有一个“发送给我”的具体实现,你的接收器只知道如何重建发送的对象。 The command objects have a mix-in (multiply-inherited, or passed as an object at run time) that knows how to marshall and serialize the Command object; 命令对象具有混合(多次继承,或在运行时作为对象传递),它知道如何编组和序列化Command对象; you can have a second one that understands the transport mechanism. 你可以有第二个了解运输机制的人。

You send a message on a particular protocol by serializing the object and using your transport mechanism to move the serialized form to the receiver. 通过序列化对象并使用传输机制将序列化表单移动到接收器,您可以在特定协议上发送消息。 The receiver "rehydrates" the object, and invokes the appropriate methods based on the actual type sent. 接收器“重新水化”对象,并根据发送的实际类型调用适当的方法。

An example of this is Java RMI with the Serializable interface instead of using Remote. 这方面的一个例子是带有Seri​​alizable接口的Java RMI,而不是使用Remote。

I believe you should take a look on Apache ActiveMQ . 我相信你应该看看Apache ActiveMQ Actually, it is written on Java, but has option to use C++ clients and well documented also. 实际上,它是用Java编写的,但也可以选择使用C ++客户端,也有很好的文档记录。

Cheers. 干杯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM