在这第二种方法中,在末端有一个完整的圆周的接口符号代表组件提供的接口 -- “棒棒糖”是这个接口分类器实现关系符号的速记法。在末端只有半个圆的接口(又称插座)符号代表组件要求的接口(在两种情况下,接口的名字被放置在接口符号本身的附近)。即使图 4 看起来与图 3 有很大的不同,但两个图都提供了相同的信息 -- 例如,Order组件提供两个接口:OrderEntry 和 AccountPayable,而且Order组件 要求 Person接口。
组件关系的建模
当表现组件与其他的组件的关系时,棒棒糖和插座符号也必须包括一支依存箭头(如类图中所用的)。在有棒棒糖和插座的组件图上,注意,依存箭从强烈的(要求的)插座引出,并且它的箭头指向供应者的棒棒糖,如图 5 所示。
图 5:显示Order系统组件如何依赖于其他组件的组件图
图 5 显示,Order系统组件依赖于客户资源库和库存系统组件。注意在图 5 中复制出的接口名 CustomerLookup 和 ProductAccessor。 在这个例子中,这看起来可能是不必要的重复,不过符号确实允许在每个依赖于实现差别的组件中有不同的接口(和不同的名字)(举例来说,一个组件提供一个较小的必需的接口子类)。
子系统
在 UML 2 中,子系统分类器是组件分类器的一个特别版本。因为这一点,子系统符号元素象组件符号元素一样继承所有的组件符号集规则。唯一的差别是,一个子系统符号元素由subsystem关键字代替了component,如图 6 所示。
图 6:子系统元素的一个例子
UML 2 规范在如何区别子系统与组件方面相当含糊。从建模的观点,规范并不认为组件与子系统有任何区别。与 UML 1. x 相比较,这个 UML 2 模型歧义是新的。但是有一个理由。在 UML 1. x 中,一个子系统被认为是一个软件包,而且这个软件包符号正对许多 UML 实践者造成困惑;因此,UML 2中把子系统作为特殊的组件,因为这是最多的 UML 1. x 使用者了解它的方式。这一改变确实把模糊引入图中,但是这一模糊更多的是 UML 2 规范中对抗错误的一个现实反射。
到这里,你可能正在抓着头皮并感到疑惑,什么时候该用组件元素,什么时候又该用子系统元素。相当坦率地说,我没有一个直接的答案给你。我可以告诉你,UML 2 规范中说,何时该使用组件或子系统决定于建模者的方法论。我个人很喜欢这个答案,因为它帮助确保UML与方法论相互独立,这在软件开发中将帮助保持它的普遍可使用。
超越基础
组件图是比较容易理解的图之一,因此没有很多超越基础的内容。然而,有一个方面你可以认为是略微困难的。
显示组件的内部结构
有时候显示组件的内部结构是有意义的。在关于类图的我的前面的文章中,我显示了该如何为类的内部结构建模;这里,当它由其他组件组成的时候,我将会关注如何为组件的内部结构建模。
为了显示组件的内部结构,你只需把组件画得比平常大一些并在名字区内放置内部的部分。图 7 显示Store组件的内部结构。
图 7: 这个组件的内部结构由其他组件组成。
使用在图 7 中显示的例子,Store组件提供了 OrderEntry 接口并要求Account接口。Store组件由三个组件组成:Order,Customer和Product组件。注意Store的 OrderEntry 和Account接口符号在组件的边缘上为何有一个方块。这一个方块被称为一个端口。单纯感觉来说,端口提供一种方法,它显示建模组件所 提供/要求 的接口如何与它里面的部分相关联。4 通过使用端口,我们可以从外部实例中分离出Store组件的内部部件。在图 7 中,对于过程而言,OrderEntry 端口代表Order组件的 OrderEntry 接口。同时,内部的Customer组件要求的Account接口被分配到Store组件的必需的Account端口。通过连接Account端口,Store组件内部部件(例如Customer组件)可以有代表执行端口接口的未知外部实体的本地特征。必需的Account接口将会由Store组件的外部组件实现。5
在图 7 中,你可能也注意到了,在内部的组件之间的内部连接与图 5 中显示的那些不同。这是因为内部结构的这些描绘事实是嵌套在分类器(在我们的例子中是一个组件)里的协作图,因为协作图显示分类器中的实体或角色。在内部的组件之间建模的关系以 UML 称为的一个组合连接器表示。一个组合连接器绑定一个组件 提供 的接口到另外的一个组件的 必需 接口。组合连接器用紧紧相连的棒棒糖和插座符号表示。以这种方式画这些组合连接器使棒棒糖和插座成为很容易理解的符号。
结论
组件图经常是一个架构师在项目的初期就建立的非常重要的图。然而,组件图的有用性跨越了系统的寿命。组件图是无价的,因为它们模型化和文档化了一个系统的架构。因为组件图文档化了系统的架构,开发者和系统可能的系统管理员会发现这一工作的关键产品有助于他们理解系统。
组件图也视为软件系统配置图的输入,这将会是本系列后面的文章主题。
脚注
1在UML1.x 中称为组件的实际项目,在 UML 2 中称为产物。一个产物是一个物理单位,象一个文件,可运行的程序,脚本,数据库等等。只有一种产物依赖于实际的节点;类和组件没有“位置”。然而,一个产物可能显示组件和其他的分类器(例如类)。一个单一的组件可能通过多重产物显示,它们可能是在相同的或不同的节点上,因此,一个单一的组件可以间接地在多重节点上被实现。
2即使组件是独立的单元,它们仍然可能依赖于其他组件提供的服务。由于这一点,文档化一个组件的必需接口是很有用的。
3图3并不显示Order组件完整的上下文。在一个真实的模型中,OrderEntry,AccountPayable 和Person接口会呈现在系统的模型中。
4事实上,端口适用于任何类型的分类器(例如,一个类或者你的模型中可能会有的其他分类器)。为了使本文简洁,我在组件分类器及它们的使用中提及端口。
5一般来说,当你画一个端口和一个接口之间的依存关系时,依赖方(要求)的接口将会在运行时间内处理所有的处理逻辑。然而,这并不是一种硬性的规定 -- 对于周围的组件(举例来说,我们例子中的Store组件),使用自己的进程逻辑,而不是仅把进程委托给依赖接口,是完全可以接受的。
文章来源于领测软件测试网 https://www.ltesting.net/