UML类图关联 - 如何、何时以及为什么?

4

我通常对UML感到很困惑,这种情况也不例外。 假设我有一个接口IAnimal,类Food和Cat:

interface IAnimal {
    void Feed(Food food);
}

class Cat : IAnimal {
    void Feed(Food food) {
        //code
    }
}

我有三个关于绘制这三个元素的UML类图的问题:

  • 我假设我应该在IAnimal和Food之间或Cat和Food之间使用关联。如果是的话,关联线的一侧是否应该带箭头?如果需要,在哪一侧添加,为什么?

  • 如果我将Feed作为IAnimal方法写在图中,我是否应该在Cat类内部编写一个方法Feed,还是只编写额外的Cat方法?

  • 最重要的问题:关联应该是在IAnimal和Food之间、Cat和Food之间还是两者都有?


1
什么类型的UML图表?我猜是类图,但如果是的话,请明确说明!还有其他12种UML图表! - slim
5个回答

14

UML定义了多种关系类型。

这些关系有不同的符号表示:

  • 关联关系的基本符号是实线路径
  • 依赖关系的基本符号是虚线箭头
  • 泛化关系的基本符号是带有三角箭头的实线路径
  • 实现关系的基本符号是带有三角箭头的虚线箭头(依赖关系和泛化关系的混合)

图示:

+---------------------------+
|       <<interface>>       |
|           IAnimal         |
+---------------------------+                        +--------+
| + Feed(food: Food) : void |- - - - <<use>> - - - ->|  Food  |
+---------------------------+                        +--------+
              ^
             /_\
              |

              |

              |
        +-----------+
        |    Cat    |
        +-----------+

即:

  • IAnimalFood之间的关系是一种使用关系,这被显示为带有«use»元素的依赖关系。
  • IAnimalCat之间的关系是一种实现关系。

关联关系用于表示两个或多个分类器之间的连接。这意味着至少一个类具有另一类型(或集合)的属性。实际上,属性和关联端包含相同的信息,并且可以互换使用。

因此,在我看来,您所描述的关系不应该被建模为关联关系。


1

你对这种东西的挑剔程度在很大程度上取决于你首先使用UML是用来做什么的。

如果你有某种神奇的UML到代码转换器,那么你需要挑剔一些(但看起来你比较喜欢代码而不是盒子和线条 - 那么你为什么要使用这样的工具呢?)

如果你只是用UML与其他人沟通,那么你可以承受一些不太挑剔的东西。

Craig Larman的“应用UML和模式”强调了这一点,包括看起来像是在白板上草绘的图表。在这种类型的图表中,实线应该是虚线,这是UML标准所说的,但实线也可以接受。箭头等也是如此。

对我来说,线应该从IAnimalFood

箭头是否增加了清晰度(对于人类读者)是一个选择问题,但它表示单向关系:

来自this introductory piece:

"在单向关联中,两个类相关联,但只有一个类知道这种关系的存在。"

1
我不同意箭头是可选的。在这种情况下,名称为你提供了明显的线索,但通常情况并非如此,文件的清晰明了至关重要。 - annakata
你是对的,但是决定记录哪些细节是由你来决定的。你可以从类图中删除所有方法,也可以选择仅为每个方法选择一些关联来绘制不同的方法。这对于将被到处都是线条的大型图表非常有用。 - Arne Burmeister
修改了我的回答以澄清。 - slim

0
假设有一个类图,你应该在IAnimal和Food之间建立一个“使用”关联,以及在Cat和IAnimal之间、Dog和IAnimal之间建立一个“是一个”关联:
    IAnimal ----> Food
     ^   ^
    //   \\
   //     \\
 Cat      Dog

箭头在“食品”旁边是什么意思?我一直认为这只是用来标识哪个类使用哪个类,但在Microsoft Visio中,在其中一个侧面设置箭头时,您必须勾选“可导航”,因此我认为它可能意味着其他东西。 - agnieszka
为什么我们不在Cat和Food之间写一个关联行呢?它也使用了Food。还是说只是“我们不这样做,就这样结束了”? - agnieszka
因为这是多余的。图表已经告诉我们动物使用食物,而猫“是”动物。因此,猫使用食物。额外的箭头会使图表混乱。 - slim
这和方法一样吗?我需要写一个Cat有一个Feed方法,还是仅仅IAnimal有一个就足够了? - agnieszka
实际上,实现一个接口不应被解释为“是一个”关系。接口是一种契约,使用它们的类正在与该契约绑定。继承是唯一表达“是一个”的关系。 - etsuba
显示剩余2条评论

0

我认为IAnimal应该有一个食物(HAVE-A Food),因为它被代谢了,但如果你真的想表示HAS-A,我认为它应该是一个聚合(open diamond)或组合符号(filled in diamond),具体取决于级联删除特性。

根据Martin Fowler的说法,UML有两种思路。有些人是“素描家”,他们使用符号在白板和纸张上传达足够的想法给其他开发人员。

然后还有那些将UML视为工程图纸的人,必须捕捉设计的每一个细节。

我坚定地站在前者的阵营中。作为一名前工程师,我可以告诉你,从个人经验来看,UML没有真正工程图纸的能力来完全捕捉软件设计。

如果你恰好相信后者,请使用UML完成完整的桌面或Web UI设计,并在此处发布。


0

1) 接口IAnimal和类型Food之间不应该有任何关联。关联仅用于连接类内部的属性与类型。例如:

class Animal
{
   Food foodEaten;
}

class Food
{
 //Implementation code
}

那么,您应该编写一个关联来指示这两种类型之间的连接。

相反,您应该绘制一种依赖关系,指示接口IAnimal依赖于类型Food。 依赖关系与上图中的关联相同,只需将直线更改为虚线。

2)不,不要编写这些方法,也不要编写依赖项。 只在接口IAnimal上留下所有注释。


据我所知,这并不正确。这是Visual Studio中类图的工作方式,但它们不是UML图。 - agnieszka

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