UML 类图关联 - 如何、何时以及为什么?
-
03-07-2019 - |
题
我经常对 UML 感到困惑,这种情况也不例外。假设我有一个接口 IAnimal,类 Food 和 Cat:
interface IAnimal {
void Feed(Food food);
}
class Cat : IAnimal {
void Feed(Food food) {
//code
}
}
关于为这 3 个元素绘制 UML 类图,我有 3 个问题:
我认为我应该使用 IAnimal 和 Food 或 Cat 和 Food 之间的关联。关联线的一侧是否应该有箭头,如果有,那么在哪一侧以及为什么有?
如果我在图表上将 Feed 编写为 IAnimal 方法,我应该在 Cat 类中编写 Feed 方法还是只编写其他 Cat 方法?
最重要的是:关联应该是 IAnimal 和 Food、Cat 和 Food 之间,还是两者之间?
解决方案
UML定义了一些 关系 类型。
关系有多种不同的表示法:
- 关联关系具有实体路径的基本符号
- 依赖关系有一个虚线箭头的基本符号
- 泛化关系的基本符号是带有三角形箭头的实线路径
- 实现关系具有带有三角形箭头的虚线箭头的基本符号(依赖性和泛化的混合)
形象地
+---------------------------+
| <<interface>> |
| IAnimal |
+---------------------------+ +--------+
| + Feed(food: Food) : void |- - - - <<use>> - - - ->| Food |
+---------------------------+ +--------+
^
/_\
|
|
|
+-----------+
| Cat |
+-----------+
那是:
- 之间的关系
IAnimal
和Food
是一个 用法 关系。这显示为与构造型“use”的依赖关系 - 之间的关系
IAnimal
和Cat
是一个 实现 关系。
关联关系用于表示 连接 两个或多个分类器之间。这意味着至少有一个类具有 属性 另一种类型(或集合)。事实上,属性和关联端包含相同的信息并且可以互换。
因此,恕我直言,您描述的关系不应建模为关联。
其他提示
假设有一个类图,您应该在 IAnimal 和 Food 之间有一个“use”关联,在 Cat 和 IAnimal 以及 Dog 和 IAnimal 之间有一个“is a”关联:
IAnimal ----> Food
^ ^
// \\
// \\
Cat Dog
您对这类东西的挑剔程度在很大程度上取决于您最初使用 UML 的目的。
如果您有某种奇特的 UML 到代码转换器,那么您需要挑剔(但看起来您对代码比对框和线更舒服 - 那么您为什么要使用这样的工具?)
如果您只是使用 UML 与其他人进行交流,那么您可以不那么挑剔。
Craig Larman 的“应用 UML 和模式”强调了这一点,其中包含看起来像是在白板上绘制的图表。UML 标准规定应该加点的实线在这种图中就可以了。所以还有箭头等等。
我很清楚这条线应该从 IAnimal
到 Food
.
箭头是否增加清晰度(对于人类读者而言)是一个选择问题,但它表示单向关系:
从 这篇介绍性文章:
"在单向关联中,两个 类是相关的,但只有一个 类知道 存在"。
我认为 IAnimal 会有 HAVE-A 食物,因为它会被代谢,但如果你真的想表示 HAS-A,我认为它应该是一个聚合(空心菱形)或组合符号(填充菱形),具体取决于级联删除特性。
Martin Fowler 认为 UML 有两种思想流派。还有“草图绘制者”,他们使用白板和奇怪的纸上的符号向其他开发人员传达足够的想法。
还有一些人将 UML 视为工程图,必须捕捉设计的每一个细节。
我坚定地站在前一个阵营。作为一名前工程师,我可以根据个人经验告诉您,UML 不具备真实工程图的力量来完全捕获软件设计。
如果您碰巧相信后者,请使用 UML 进行完整的桌面或 Web UI 设计并将其发布在此处。
1) 接口 IAnimal 和 Food 类型之间不应编写任何关联。关联仅用于将类型与类内的属性连接起来。例如
class Animal
{
Food foodEaten;
}
class Food
{
//Implementation code
}
那么你应该编写一个关联来指示这两种类型之间的联系。
相反,您应该绘制一个依赖项,表明接口 IAnimal 依赖于 Food 类型。依赖关系的绘制方式与上图关联相同,只是将直线改为点线即可。
2)不,不要编写那些方法,也不要编写依赖项。仅将所有符号保留在 IAnimal 界面上