如何理解UML中类似于自反关联的“自反聚合”关系

Posted

技术标签:

【中文标题】如何理解UML中类似于自反关联的“自反聚合”关系【英文标题】:How to understand the "reflexive aggregation" relationship similar to reflexive association in UML 【发布时间】:2022-01-15 15:43:52 【问题描述】:

这个类图是什么意思?自反关联的类图使用实线和箭头,但这里用空心菱形代替。它与递归有关吗?这个类图会生成什么?最好能举个例子。另外,这个递归关系应该是一对多的,如果存储了数据库怎么建表呢。

【问题讨论】:

感谢@Christophe 的回复我明白了,也就是说这种类图可以描述一个树形结构。通俗的讲,可以看成是一所大学有多个系,每个系包含多个专业,而这些子节点只有一个共同的父节点。但是如果要设计一个Unit程序的类图,如何画出边界类、控制类、实体类,才能更好的表达面向对象设计的精髓呢?如果我能举个例子就好了。 有很多方法。 Enity-Boundary-Control 需要从用例开始,因为控制类对应于用例,边界对应于它们与参与者的关联。还有其他 OO 设计方法,因此它也将取决于架构选择。但是将所有类都放在一个图中仅适用于小型系统。因此,一种流行的方法是从域模型(即 ECB 中的实体)开始,并使用其他模型来展示域类如何与 UI 和应用程序基础架构协作。 但这些是不同的问题。在 *** 上,每个问题都应该有一个非常狭窄的焦点,这样才能客观地回答。 我觉得我有一个宏观的理解,非常感谢 【参考方案1】:

什么意思?

这个类图意味着Unit的一个实例可以Unit的其他几个实例相关联:

空心聚合菱形只是一个“modeling placebo”:它并没有改变图表的含义,只是暗示该关联代表某种分组。

自反关联意味着它将一个类与其自身相关联。与递归没有直接关系,如this SO answer explains。

尽管如此,递归 算法是探索此类关联的良好候选者(例如,查找与特定实例间接相关的 Unit 的所有实例)。在数据库环境中,有时使用术语“递归关联”而不是“自反”,因为用于实现它们的 recursive joins。

请注意,1 可能应该是 0..1,因为 1 正好是 1,这意味着向上导航时会有无限循环。

它看起来怎么样?

由于它是一对多关联,您可以将其可视化为一片树林:每个Unit 实例都可以是一些分支的开始并且几棵树可能共享公共分支罢工>(废话:最多只有一个父母)

生成什么/如何实现?

让我们添加一些角色来更好地说明聚合的结束:

代码生成将取决于工具和目标语言。但是具有聚合的模型和具有简单关联的模型很可能会生成完全相同的代码,例如:

class Unit  // Java
    private String id;
    private Unit[] child; // java objects are sharable by default 
    private Unit parent; // unless we make it non navigable in that direction
    ...

在 RDBMS 中,表看起来非常相似。关系模型允许只使用一列进行双向链接:

ID (PK)  |  Parent (FK, nullable)
----------------------------------
w        |
u        |
u1       |  u
u2       |  u 
u3       |  u
u21      |  u2
u31      |  u3
u32      |  u3 
v        |
v2       |  v

self-join or a recursive CTE 将允许使用自反关联查询数据。

【讨论】:

我不同意。除非在您指定特殊语义的域中,否则不应使用空心菱​​形。 OP的问题不是这种情况。 @qwerty_so 我认为我们可以同意不建议这样做的事实。但是,规范定义了共享聚合。它甚至暗示它可以用来表示某种分组(该语句几乎是从规范中复制粘贴的),即使没有指定的语义。所以我们也不能忽视它。就像任何安慰剂一样,你可以用也可以不用,结果是一样的,但有些人会感觉更好;-) OP 询问其含义是什么,而不是它应该是什么。您显示的代码应该是模型,而不是模型。 @JimL。感谢您强调我们的不同方法。我看到您选择强调 1 多重性,这很明显。我认为 1 是一个简单的错误,而 OP 对有无钻石之间的区别更感兴趣。当我阅读了无数关于聚合与关联的矛盾声明时,我推断这让大多数 OP 感到困惑。也许我的解释是错误的。但是,Java 代码显示了什么是 AND 应该是什么:如果没有显示构造函数,Java 类中 0..1 或 1 的多重性没有区别 ;-) @JimL。我看到 qwerty_so 还假设聚合处于危险之中,并且没有解决 1 的不一致问题。【参考方案2】:

我是UML,这个类意味着每一个单元都被聚合到其他的单元中。

UML 标准不包括代码生成,因此将其解释为代码取决于您选择的工具。每个专有的代码生成工具应该要么因错误而停止,要么提供一个额外的构造函数来创建一个引用自身的新单元。否则,调用者将什么 Unit 传递给第一个 Unit 的构造函数?

解决此问题的其他方法包括对此 UML 模型进行开放世界的解释(其中并非所有真实信息都存在,如 OWL 的情况),或将多重性放宽到 0..1。

【讨论】:

为什么代码生成工具会因错误而停止:拥有一个自引用循环数据结构不是完全合法的吗(circular buffer 是一个完美的例子,谁知道是否循环多缓冲区不是另一个有前途的新发明;-))。此外,为什么代码生成工具要由于自反关联而递归?生成代码不使用类实例,因此潜在循环不会影响代码生成。使用任何代码生成器进行的快速测试都可以证明这一点。 按照模型,任何 Unit 没有引用另一个 Unit 是错误的,这是不可能的(除非一个 Unit 引用它自己)。 我之前评论中的括号让我意识到我错过了另一种可能性。我相应地更新了我的答案。 构造函数不在模型中。所以代码生成根本不会受到这方面的困扰。事实上,我快速测试的那个,只是生成了一个带有属性的类。代码生成器只生成什么是应该的;-) 如果需要添加构造函数,建模者必须指定一个与模型一致的构造函数。预见到创建自引用单元是没有问题的;操作完全未指定,无论如何这完全是推测性的。【参考方案3】:

P。对于这种关系,UML 2.5 中有 110 个状态:

shared - 表示该属性具有共享聚合语义。共享聚合的精确语义因应用领域和建模者而异。

简而言之:它意味着你定义它应该意味着什么。


历史笔记

在 UML 1.5 中只有聚合。然后在 2.0 中,他们引入了共享聚合。在页。 UML 2.0 的 80 个

表示该属性具有共享聚合。

再往下

共享聚合的精确语义因应用领域和建模者而异。

很明显,后一句话还没有被普通人理解,你会发现各种各样的解释来解释它的含义。

幸运的是,现在在 UML 2.5 中,这两个句子被合并到一个段落中。即在我著名的 p 上。 110.

【讨论】:

以上是关于如何理解UML中类似于自反关联的“自反聚合”关系的主要内容,如果未能解决你的问题,请参考以下文章

UML中四大关系

UML知识精华

02.UML类图

UML中双向关系的特点?

设计模式存在哪些关联关系,六种关系傻傻分不清--- UML图示详解

设计模式存在哪些关联关系,六种关系傻傻分不清--- UML图示详解