UML信号最常见的翻译成C++的方式是什么?

3

将UML信号及其接收器翻译成C++最常用的方法是什么?在C++中,信号及其接收器的等效物是什么?

归根结底,它只是一个方法调用吗?


请搜索“事件聚合器模式”、“观察者模式”、“发布-订阅模式”和“boost信号”。没有正确或错误的方法。如果对象关系是1:1,则可以直接调用方法。 - selbie
3个回答

3

来自 Rational UML 文档:

https://www.ibm.com/docs/en/rational-soft-arch/9.7.0?topic=diagrams-signals

在 UML 模型中,信号是独立于处理它们的分类器的模型元素。信号指定了主动对象之间的单向异步通信。信号经常用于事件驱动系统和分布式计算环境中。例如,通信系统可能包含一个 Pager 类,其对象等待并响应页面信号。信号与其他消息类型不同之处在于当对象接收到信号时,对象不需要返回任何东西,而是根据其接收行为指定的行为对接收到的信号做出反应。

所有信号都被认为具有 send() 操作。信号的属性表示其在发送操作中携带的数据。信号不能具有其他操作。

换句话说,UML 中的“信号”(以及“接收器”,“事件”等)是映射到您的应用程序的抽象。它们不是“语言构造”本身。

更具体地说,当您的应用程序实现一个“信号(signal)”时,它可能有一个名为“send()”的C++函数或类方法。Send() 可能会发送一个 Posix 信号(例如 kill()),也可能会将某些内容发布到消息队列(message queue)或其他无数个不同的可能性。
简而言之,如果您的“设计”指定了UML“信号”,那么您的C++代码将完全取决于您选择的任何“实现”。
从这个意义上说,没错:在最后一天,“它只是一个方法调用" :)

2
尽管paulsm4的答案已经是正确的,但我想补充一下UML作者关于信号的说法。在UML 2.5的第167页中可以找到以下内容:
10.3.3.1信号 信号是对象之间一种异步触发反应而无需回复的通信方式的规范。接收对象根据第13.3条指定的方式处理信号。通信携带的数据表示为信号的属性。信号的定义独立于处理它的分类器。
发送信号的对象不会阻塞等待回复,而是立即继续执行。通过声明与给定信号相关联的接收,分类器指定其实例将能够接收该信号或其子类型,并将使用指定的行为对其做出响应。
信号可以被参数化、绑定并用作模板参数。
10.3.3.2接收器 接收器指定其所属的类或接口准备好对信号的接收作出反应。如果接收到的信号是接收器信号的特化,则接收器匹配信号。对象对接收到的信号做出响应的详细信息取决于与接收器及其所属的类或接口相关联的行为类型。参见第13.2节。接收器名称与信号名称相同。接收器只能具有与信号的属性匹配的输入参数(参见9.4.3),名称、类型和重数。
由于UML本身与语言无关,这就是你所拥有的全部。任何编译器/编码器如何实现这一点完全是开放的。

1
对于已经很出色的两个答案,我想补充一些实用方面的内容:
谁比 Booch、Rumbaugh 和 Jacobson 更好地解释信号应该是什么,他们是 UML 的发明者(也是早期 Rational 工具的创造者):

消息是由一个对象异步发送并由另一个对象接收的命名对象。信号是消息的分类器;它是一种消息类型。(...) 信号与普通类有很多共同之处。(...) 信号的属性用作其参数。
- Booch、Rumbaugh 和 Jacobson 在《UML 用户指南》第二版(第 21 章,事件和信号)中说道。

因此,在 C++ 中,信号通常会被表示为类。接收将由一个成员函数来表示,该函数带有该类的参数。
一种常见的替代方法是使用成员函数来表示它们:其参数为信号参数(在某些框架中使用此方法,例如这里用于事件这里,其中 Q_SLOT 表示 Qt 中的信号接收)。该函数应设计为异步调用。这通常足够,但会使信号的特殊化更加棘手和难以维护。
一些额外的备注:
  • 大多数类不是主动类:由于它们没有拥有自己的进程或线程,操作系统级别的信号很少是相关的实现或接收。当它们是相关的时候,通常一些回调函数将它们映射到所选择的实现。

  • 关注点分离和单一职责原则已经被采纳:对于基于类的实现,一个信号的职责应该是消息内容,而不是除了分发本身之外的其他职责(更改分发技术是侵犯SRP的另一个原因)。

    因此,发送方要么调用分发类的发送函数(事件队列,可以是观察者变体或职责链),要么直接调用接收方的“接收”函数(如果需要使用一些异步机制,如{{link3:std::future}}来使用异步调用或承诺)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接