UML中关系整理
Posted 键圣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UML中关系整理相关的知识,希望对你有一定的参考价值。
在UML中,关系是非常重要的语义,它抽象出对象之间的联系,让对象构成某个特定的结构。
1.关联关系(association)
关联关系是用一条直线表示的,如
它描述不同类的对象之间的结构关系,它在一段时间内将多个类的实例连接在一起。关联关系是一种静态关系,通常与运行状态无关,而是由“常识”,“规则”,“法律”、等因素决定的,所以关联关系是一种”强关联“的关系。
例如,公司与员工之间一对多就是一种符合“常识”的关系;乘车人和车票之间的一对一关系是符合“规则”的关系;公民和身份证之间的一对多关系是符合“法律”的关系。关联关系用来定义对象之间静态的、天然的结构。这与依赖关系是不同的,依赖关系表达的是对象之间的临时性的、动态的关系。在JAVA代码里,关联关系通常是以实例变量(成员变量)的形式实现的。与依赖相比,关联的两个对象之间通常不会相互直接使用,尽管它们相互”知道”对付的存在,但一般都是由外部对象来访问的,如一个外部访问者可以通过员工对象获得公司对象。
关联关系具有多重性,常见的为:
- 一对一关联
- 一对多关联
- 多对多关联
例如对象之间的父-子结构,如果是无方向的,表明父子对象相互拥有对付的实例变量;如果有方向的,如父到子,则表明父对象有子对象的实例变量,但子对象没有父对象的实例变量。
特别的,在用例模型中,单向关联关系用于连接参与者和用例,箭头由参与者指向用例,表示参与者”知道”用例的存在。
2.依赖关系(dependency)
依赖关系是用一条带箭头的虚线表示,如
例如人和船这两个对象,如果运行场景是开动轮船,那么轮船依赖于人(水手);如果场景变为渡海,那么变成人依赖于船了。可见,依赖关系是一种“弱”关系,它不是天然存在的,并且会随着运行场景的变化而变化。如果人和刀这两个对象,平时它们没有关系的,但是在削苹果这个场景里,人依赖于刀;脱离了这个场景,或者当场景结束后,依赖关系也就不存在了。
一般而言,依赖关系在最终的代码里体现为类构造方法,类方法等的传入参数。
与关联关系相比,依赖关系除了临时“知道”对方外,还会“使用”对付的属性或方法。从这个角度讲,被依赖的对象改变会导致依赖对象的修改。举例来说,A对象保存了B对象的实例,但A对象对B对象没有操作,这时A仅仅是“知道”B对象,应当用关联关系,并且B修改了方法以后,A并不会变化;但如果A对象在某个场景中使用了B对象的属性或方法,则B的修改会导致A的修改,这时A依赖于B。
同样的,依赖也有单向依赖和双向依赖之分。但是依赖关系却不像关联关系那样有带箭头和不带箭头的区分,统统都是带箭头的。这是因为在面向对象里,双向依赖是一种非常不好的结构,我们总是应当保持单向依赖,杜绝双向依赖关系的产生。
3.扩展关系(extends)
扩展关系是用一条带箭头的虚线加版型<<extends>>来表示的,如
它特别用于在用例模型中说明向基本用例中的某个扩展点插入扩展用例。
一般来说,扩展用例是带有抽象性质的,它表示了用例场景中的某个“支流”,由特定的扩展点触发而被启动。所以严格来说扩展用例应当用在概念用例模型中,通过分析业务用例场景抽象出关键的可选核心业务而形成扩展用例。不过,在业务模型当中使用也是可以接受的,它可以更显式地表示出一个复杂业务用例的各个“分支”。
与包含关系不同的是,扩展表示的是“可选”,而不是“必需”,这意味着即使没有扩展用例,基本用例也是完整的;如果没有基本用例,扩展用例是不能单独存在的;如果有多个扩展用例,同一时间用例也只会使用其中的一个。
在建模过程中,我们使用扩展关系可能基于以下理由:
- 表明用例的某一部分是可选(或可能可选)的系统行为。这样就可以将模型中的可选行为和必选行为分开。
- 表明只在特定条件(有时是列外条件)下才执行分支支流,如触发警报。
- 表明可能有一组行为段,其中的一个或多个段可以在基本用例的扩展点处插入。所插入的行为段(以及插入的顺序)将取决于在执行基本用例时与主角进行的交互。
为了理解扩展关系,让我们看一个例子。在打电话时,如果在通话过程中收到一个呼叫,我们可以将当前通话保留而接听另一个通话。在这个场景中,保留通话用例就像打电话用例的一个扩展用例。我们可以看到,是否保留通话取决于打电话人的决定,而不是必需,即使我们没有使用保留通话功能,也不影响打电话的完整性。但是如果没有之前的打电话用例,也就不可能单独启动所谓的保留通话用例了。
4.包含关系(include)
包含关系是用一条带箭头的虚线加版型<<include>>来表示的,如:
它特别用于用例模型,说明在执行基本用例的用例实例过程中插入的行为段。
包含用例总是带有抽象性质的,基本用例可控制与包含用例的关系,并可依赖于执行包含用力所得的结果,但基本用例和包含用例都不能访问对付的属性。从这种意义上讲,包含用例是被封装的,它代表可在各种不同基本用例中复用的行为。因此,与扩展用例一样,包含用例也应当用在概念模型中,通过分析业务用例场景而抽象出关键的必选的核心业务而形成包含用例。同样,在业务模型中使用也是可以接受的,它可以显式地表示出那些可复用的业务过程。
与扩展用例不同的是,包含用例表示的是“必需”而不是“可选”,这意味着如果没有包含用例,基本用例是不完整的,同时如果没有基本用例,包含用例是不能独立存在的。
在建模过程中使用包含关系可能基于以下理由:
- 从基本用例中分解出这样的行为:它对于了解基本用例的主要目的并不是必需的,只有它的结果才比较重要。
- 分解出两个或更多用例共有的行为。
5.实现关系(realize)
实现关系是用一条带空心箭头的虚线表示的,如它特别用于在用例模型中连接用例和用例实现,说明基本用例的一个实现方式。
实现所代表的含义是,基本用例描述了一个业务目标,但是该业务目标有多种可能的实现途径,每一种实现途径可以用用例实现(或称用例实例)来表示,而用例实现与基本用例之间就构成了实现关系。换而言之,每个实现途径都实现了基本用例的业务目标。
6.精化关系(refine)
精化关系是用一条带箭头的虚线加版型<<refine>>来表示的,如它特别用于用例模型,一个基本用例可以分解出许多更小的关键精化用例,这些更小的精化用例更细致地展示了基本用例的核心业务。精化关系用来连接基本用例和精化用例,说明精化用例是由基本用例精化得来的。
精化关系也可以用于模型与模型之间,表示某个模型是通过精化另一个模型而得来的。比如说,我们认为设计类是通过分析类而得来的,我们可以使用XX设计类<<refine>>XX分析类来表示它们之间的关系。
与泛化关系不同的是,精化关系表示由基本对象可以分解为更明确、精细的子对象,这些子对象并没有增加、减少、改变基本对象的行为和属性,仅仅是更加细致和明确化了。在泛化关系中,基本对象被泛化为子对象后,子对象继承了基本对象的所有特征,并且子对象可以增加、改变基本对象的行为和属性。
另一方面,精化关系仅仅用于建模阶段,在实现语言中是没有精化这一语意的。泛化则等同于实现语言中的继承语意。
7.泛化关系(generalization)
泛化关系是用一条带空心箭头的直线表示的,如泛化关系可用于建模过程中的任意一个阶段,说明两个对象之间的继承关系。读者对面向对象中的继承应该不会陌生,泛化关系表示一个类对另一个类的继承。继承而得的类称为后代。被继承的类称为祖先。继承意味着祖先的定义(包括任何特征,如属性、关系或对其对象执行的操作)对于后代的对象也是有效的。泛化关系是从后代类到其祖先类的关系。
特别需要说明的是,作者并不赞同在用例之间使用泛化关系,尽管UML认为它是合法的。原因是用例带有原子特性,每个用例都应当是独一无二的。用例描述了参与者完成一个目标的整个过程,如果采用泛化关系,很难描述子用例继承了基本用例的什么。过程还是业务实体?如果仅仅为了将用例之间的可复用部分或用例的可扩展部分描述出来,那么使用包含关系和扩展关系就足够了。
8.聚合关系(aggregation)
聚合关系是用一条带空心棱形箭头的直线表示的,如(A聚合到B上,或者说B由A组成)。
聚合关系用于类图,特别用于表示实体对象之间的关系,表达整体由部分构成的语意。例如一个部门由许多人员构成。
与组合关系不同的是,整体和部分不是强依赖的,即使整体不存在了,部分仍然存在。例如部门撤销后,人员不会因此而消失,他们依然存在。
9.组合关系(composition)
组合关系是用一条带实心棱形箭头的直线表示的,如(A组合成B,或者说B由A构成)。
组合关系用于类图,特别用于表示实体对象关系,表达整体拥有部分的语意。例如母公司拥有许多子公司。
组合关系是一种强依赖的特殊聚合关系,如果整体不存在了,则部分也将消亡。例如母公司解体了,子公司也将不存在。
以上是关于UML中关系整理的主要内容,如果未能解决你的问题,请参考以下文章