统一建模语言(Unified Modeling Language, UML )是一种为面向对象系统的产品进行说明、可视化和编制文档的一种标准语言,是非专利的第三代建模和规约语言。 UML 是面向对象设计的建模工具,独立于任何具体程序设计语言。
一、简介
UML 作为一种统一的软件建模语言具有广泛的建模能力。 UML 是在消化、吸收、提炼至今存在的所有软件建模语言的基础上提出的,集百家之所长,它是软件建模语言的集大成者。 UML 还突破了软件的限制,广泛吸收了其他领域的建模方法,并根据建模的一般原理,结合了软件的特点,因此具有坚实的理论基础和广泛性。 UML 不仅可以用于软件建模,还可以用于其他领域的建模工作。
UML 立足于对事物的实体、性质、关系、结构、状态和动态变化过程的全程描述和反映。 UML 可以从不同角度描述人们所观察到的软件视图,也可以描述在不同开发阶段中的软件的形态。 UML 可以建立需求模型、逻辑模型、设计模型和实现模型等,但 UML 在建立领域模型方面存在不足,需要进行补充。
作为一种建模语言, UML 有严格的语法和语义规范。 UML 建立在元模型理论基础上,包括 4 层元模型结构,分别是基元模型、元模型、模型和用户对象。4 层结构层层抽象,下一层是上一层的实例。 UML 中的所有概念和要素均有严格的语义规范。
UML 采用一组图形符号来描述软件模型,这些图形符号具有简单、直观和规范的特点,开发人员学习和掌握起来比较简单。所描述的软件模型,可以直观地理解和阅读,由于具有规范性,所以能够保证模型的准确、一致。
二、作用
概括起来说,UML 主要有以下作用:
1. 为软件系统建立可视化模型。
UML 符号具有良好的语义,不会引起歧义;基于 UML 的可视化模型,使系统结构直观、易于理解;使用 UML 进行软件系统的模型不但有利于系统开发人员和系统用户的交流,还有利于系统维护。模型是系统的蓝图,它可以对开发人员的规划进行补充,模型可以帮助开发人员规划要建的系统。有了正确的模型就可以实现正确的系统设计,保证用户的要求得到满足,系统能在需求改变时站得住脚。对于一个软件系统,模型就是开发人员为系统设计的一组视图。这组视图不仅描述了用户需要的功能,还描述了怎样去实现这些功能。
2. 为软件系统建立构件。
UML 不是面向对象的编程语言,但它的模型可以直接对应到各种各样的编程语言。例如,它可以使用代码生成器工具将 UML 模型转换为多种程序设计语言代码,如可生成 C++,XML,DTD,JAVA, Visual basic 等语言的代码,或使用反向生成器工具将程序源代码转换为 UML ;甚至还可以生成关系数据库中的表。
3. 为软件系统建立文档。
UML 可以为系统的体系结构及其所有细节建立文档。不同的 UML 模型图可以作为项目不同阶段的软件开发文档。
三、模型
UML 系统开发中有三个主要的模型:
- 功能模型:从用户的角度展示系统的功能,包括用例图。
- 对象模型:采用对象,属性,操作,关联等概念展示系统的结构和基础,包括类别图、对象图。
- 动态模型:展现系统的内部行为。包括序列图,活动图,状态图。
四、组成
UML 由模型元素(Model Element)、图(Diagram)、视图(View)和通用机制 (General Mechanism)等几个部分组成。
- 模型元素
代表面向对象中的类、对象、消息和关系等概念,是构成图的最基本的常面向对象系统分析与设计方法用概念。
- 图
是模型元素集的图形表示,通常是由弧(关系)和顶点(其他模型元素)相互连接构成的。
- 视图
是表达系统的某一方面的特征的 `UMI`,建模元素的子集,由多个图构成,是在某一个抽象层上,对系统的抽象表示。
- 通用机制
用于表示其他信息,比如注释、模型元素的语义等。另外,UML还提供扩展机制,使 UML 语言能够适应一个特殊的方法(或过程),或扩充至一个组织或用户。
五、图例
区分 UML 模型和 UML 图是非常重要的,UML 图,包括用例图、协作图、活动图、序列图、部署图、构件图、类图、状态图,是模型中信息的图形表达方式,但是 UML 模型独立于 UML 图存在。UML 的当前版本只提供了模型信息的交换,而没有提供图信息的交换。
UML 使用一套与 Java 语言或其他面向对象语言等价物,同时也是本体论等价物的图形标记。
UML 并不是一个方法学,也不要求使用一个方法学,但是 UML 对于 Rational 统一过程来说是必不可少的。
下面 UML 中的主要图例的功用做一个简单介绍:
- 用例图
描述角色以及角色与用例之间的连接关系。说明是谁要使用系统,以及他们使用该系统可以做些什么。一个用例图包含了多个模型元素,如系统、参与者和用例,并且显示了这些元素之间的各种关系,如泛化、关联和依赖。
- 类图
类图是描述系统中的类,以及各个类之间的关系的静态视图。能够让我们在正确编写代码以前对系统有一个全面的认识。类图是一种模型类型,确切地说,是一种静态模型类型。类图表示类、接口和它们之间的协作关系。
- 对象图
与类图极为相似,它是类图的实例,对象图显示类的多个对象实例,而不是实际的类。它描述的不是类之间的关系,而是对象之间的关系。
- 活动图
描述用例要求所要进行的活动,以及活动间的约束关系,有利于识别并行活动。能够演示出系统中哪些地方存在功能,以及这些功能和系统中其他组件的功能如何共同满足前面使用用例图建模的商务需求。
- 状态图
描述类的对象所有可能的状态,以及事件发生时状态的转移条件,可以捕获对象、子系统和系统的生命周期。它可以告知一个对象可以拥有的状态,并且事件(如消息的接收、时间的流逝、错误、条件变为真等)会怎么随着时间的推移来影响这些状态。一个状态图应该连接到所有具有清晰的可标识状态和复杂行为的类;该图可以确定类的行为,以及该行为如何根据当前的状态变化,也可以展示哪些事件将会改变类的对象的状态。状态图是对类图的补充。
- 序列图(时序图)
序列图是用来显示参与者如何以一系列顺序的步骤与系统的对象交互的模型。顺序图可以用来展示对象之间是如何进行交互的。顺序图将显示的重点放在消息序列上,即强调消息是如何在对象之间被发送和接收的。
- 协作图
和序列图相似,显示对象间的动态合作关系。可以看成是类图和顺序图的交集,协作图建模对象或者角色,以及它们彼此之间是如何通信的。如果强调时间和顺序,则使用序列图;如果强调上下级关系,则选择协作图;这两种图合称为交互图。
- 构件图(组件图)
描述代码构件的物理结构以及各种构建之间的依赖关系。用来建模软件的组件及其相互之间的关系,这些图由构件标记符和构件之间的关系构成。在组件图,构件时软件单个组成部分,它可以是一个文件,产品、可执行文件和脚本等。
- 部署图(配置图)
用来建模系统的物理部署。例如,计算机和设备,以及它们之间是如何连接的。部署图的使用者是开发人员、系统集成人员和测试人员。部署图用于表示一组物理结点的集合及结点间的相互关系,从而建立了系统物理层面的模型。
六、类图
6.1 类图基础属性
类图概括起来主要由两部分组成 —— 类、类之间的关系, 其中对类的定义如上图所示, 主要由三部分组成, 它们是类名、 类的属性(成员变量)、 类的相关操作(函数方法), 分别对应图里的上中下三个分区内容。
[ 符号解释 ]
- -:private
- +:public
- ~:default
- #:protected
- 下划线:static
- 斜体:抽象 (注意也可以用两个尖括号包裹来表示抽象,比如 —— <<我是抽象类 or 接口>>)
- 冒号前是方法名/变量名(根据有无括号区分),冒号后是返回参数/变量类型(根据有无括号区分),如果没有冒号的话表示方法返回空(也有人通过:void 表示返空)
6.2 泛化关系(你可以理解为继承)
标准解释:泛化关系为 is-a 的关系;两个对象之间如果可以用 is-a 来表示,就是泛化关系 。
通俗解释:Mac is a 电脑,懂了吧 ? 也就是说 Mac 继承 了电脑,是电脑的子类 。
总结:空心(也有实心表示的,你反正记住这个形状就行)三角 + 实线 == 继承关系
6.3 实现关系
标准解释:程序里面实现关系表现为继承抽象类 。
通俗解释:继承抽象类和实现接口都属于实现关系 。 需要特别注意的是实现关系有种 "棒棒糖" 表示法,就是被实现的那个对象是用圆形表示的(这个在下面巩固栏目里会说明)。
总结:空心(也有实心表示的,你反正记住这个形状就行)三角 + 虚线 == 实现关系
6.4 关联关系
标准解释:通常用一条直线表示,当然如果需要标明方向可以添加箭头。它是描述不同的类对象之间的关系,通常不会随着状态的变化而变化,可以理解为被关联者属于关联者的一部分。
通俗解释:其实就是一个类中的对象与对象之间的引用关系,你可以理解为一个类中的 所有 成员变量 。 当然如果是多对多关系(比如一个类中的成员变量含有另一个对象的 List, 另一个类的成员变量又含有当前对象的 List), 那么就可以不用箭头表示, 也可以用双向箭头表示。
总结:尖括号 + 实线 == 关联关系
6.4.1 组合关系(组合关系是关联关系的一种,属于强关联关系)
标准解释:与聚合关系一样,组合关系同样表示整体由部分构成的关系,不同之处在于整体和部分是强依赖关系,如果整体不存在了,部分也不复存在。
通俗解释:你可以直接理解为非集合类的成员变量, 它与类共存亡 。
总结:实心 棱形 + 实线 == 组合关系
> 需要另外注意的是,组合关系可特殊标明 0..1(0 至 1)、n(规定数量) 、0..*(0 至多) 、 1..* (1 至多)、 m..n(规定的数量区间)。比如棱形一头是 1,而另一头是 1 … \* —— 那它的意思就是 “1” 对 “多”,且这个“多”最少为一个。
6.4.2 聚合关系( 聚合关系也是关联关系的一种,属于弱关联关系 )
标准解释:与组合关系不同的是,整体和部分不是强依赖的,即使整体不存在了,部分仍然存在。
通俗解释:你可以理解为 集合类的成员变量, 集合类中聚合的对象就代表
了这层聚合关系 。如 List<码农> ,这个集合中 聚合 的“码农”对象是可有可无的, 他不影响自身, 这就是聚合关系 。
总结:空心 棱形 + 实线 == 聚合关系
6.5 依赖关系
标准解释:通常描述一个对象在运行期间会用到另一个对象的关系。
通俗解释:当一个对象依赖另一个对象提供的服务时,就是依赖关系 。 函数方法的入参 、 局部变量的引用 、 静态方法的直接调用 都属于这个范畴 。 一个对象中的函数方法依赖另一个对象作为实例入参的表现形式最为常见, 拿函数方法举例 —— 比如 A 函数方法的入参实例 B,就是需要依赖过来的调用对象。
总结:尖括号 + 虚线 == 依赖关系
6.6 案例
图中的意思概括就是:
1. 一个 公司 中可以有多个 部门 —— 非集合类的成员变量(公司亡,部门必亡)
2. 一个 部门 中可以有多个 码农 —— 集合类成员变量,如 List<码农>(码农可有可无,没了换掉就是了,不影响部门的存活)
3. 一个 码农 可以有多个 手机 —— 成员变量
4. 一个 码农 依赖多个 Mac —— 很简单,有了 Mac 我才能敲代码嘛,可以理解为需要 Mac 来完成自身的方法调用
5. Mac 是 电脑 的一种拓展 —— 继承关系
6. 电脑 是 可处理计算机 这个概念的一种实现 —— 实现关系
七、时序图
7.1 时序图的作用是什么?
1. 展示对象之间交互的顺序。将交互行为建模为消息传递,通过描述消息是如何在对象间发送和接收的来动态展示对象之间的交互;
2. 相对于其他 `UML` 图,时序图更强调交互的时间顺序;
3. 可以直观的描述并发进程。
7.2 组成元素
7.2.1 角色(Actor)
系统角色,可以是人、机器、其他系统、子系统;在时序图中用表示。
7.2.2 对象(Object)
对象的三种命名方式
第一种方式包括对象名和类名,例如:直播课时:课时,在时序图中,用“对象:类”表示;
第二种方式只显示类名,即表示它是一个匿名对象,例如: :课程;在时序图中,用“:类”表示;
第三种方式只显示对象名不显示类名,例如:讲师;在时序图中,用“对象”表示。
命名方式的选择
三种命名方式均可,哪种最容易让阅读该时序图的人理解,就选择哪种。
对象的排列顺序
对象的左右顺序并不重要,但是为了作图清晰整洁,通常应遵循以下两个原则:
①. 把交互频繁的对象尽可能的靠拢;
②. 把初始化整个交互活动的对象放置在最左端。
7.2.3 生命线(Lifeline)
在时序图中表示为从对象图标向下延伸的一条虚线,表示对象存在的时间。
7.2.4 控制焦点(Focus of Control)
又称为激活期,表示时间段的符号,在这个时间段内对象将执行相应的操作。它可以被理解成 C 语言语义中一对花括号{ }中的内容;用小矩形表示。
7.2.5 消息(Message)
消息一般分为同步消息(Synchronous Message),异步消息(Asynchronous Message)和返回消息(Return Message)。
消息的发送者把控制传递给消息的接收者,然后停止活动,等待消息的接收者放弃或者返回控制。用来表示同步的意义;
消息发送者通过消息把信号传递给消息的接收者,然后继续自己的活动,不等待接受者返回消息或者控制。异步消息的接收者和发送者是并发工作的。
返回消息表示从过程调用返回。
7.2.6 自关联消息
表示方法的自身调用或者一个对象内的一个方法调用另外一个方法。
7.2.7 组合片段
组合片段用来解决交互执行的条件和方式,它允许在序列图中直接表示逻辑组件,用于通过指定条件或子进程的应用区域,为任何生命线的任何部分定义特殊条件和子进程。组合片段共有 13 种,名称及含义如下:
常用组合片段举例:
用来指明在两个或更多的消息序列之间的互斥的选择,相当于经典的 if..else..
1. 抉择(Alt)
抉择在任何场合下只发生一个序列。 可以在每个片段中设置一个临界来指示该片段可以运行的条件。else 的临界指示其他任何临界都不为 True 时应运行的片段。如果所有临界都为 False 并且没有 else,则不执行任何片段。
2. 选项(Opt)
包含一个可能发生或不发生的序列;
3. 循环(Loop)
片段重复一定次数,可以在临界中指示片段重复的条件。
4. 并行(Par)
7.4 总结
时序图的绘制技巧:
1. 从初始消息开始画,依次画出随后消息,并给每个消息分配序号,方便理解。
2. 角色和对象用名词,消息用动词。
3. 角色放在时序图的开始位置,对象重要程度或使用频率从左到右排列。这就要根据时间的流程考虑了,是一个比较主观的事情。
4. 控制焦点两端要以消息元素封顶,控制焦点不要超过消息元素。
八、用例图
8.1 组成
1. 用例(Use Case)
2. 参与者(Actor)
3. 关系(依赖、泛化以及关联)
8.2 箭头关系
<table><tr><th colspan="2">关系</th><th>解释</th><th>图</th></tr><tr><td>参与者与用例之间的关系</td><td>关联</td><td>表示参与者与用例之间的交互,通信途径。(关联有时候也用带箭头的实线来表示,这样的表示能够显示地表明发起用例的是参与者。)</td><td>___________</td></tr><tr><td rowspan="2">用例之间的关系</td><td>包含</td><td>箭头指向的用例为被包含的用例,称为包含用例;箭头出发的用例为基用例。包含用例是必选的,如果缺少包含用例,基用例就不完整;包含用例必须被执行,不需要满足某种条件;其执行并不会改变基用例的行为。</td><td>《include》<br/>--------------></td></tr><tr><td>扩展</td><td>箭头指向的用例为被扩展的用例,称为扩展用例;箭头出发的用例为基用例。扩展用例是可选的,如果缺少扩展用例,不会影响到基用例的完整性;扩展用例在一定条件下才会执行,并且其执行会改变基用例的行为。</td><td>《extend》<br/>--------------></td></tr><tr><td>参与者之间的关系</td><td>泛化</td><td>发出箭头的事物“is a”箭头指向的事物。泛化关系是一般和特殊关系,发出箭头的一方代表特殊的一方,箭头指向的一方代表一般一方。特殊一方继承了一般方的特性并增加了新的特性。</td><td>《extend》<br/><img src="img\image-20220828141140275.png"/></td></tr>
</table>
用例图的主要元素是用例和参与者:所谓用例是指对系统提供的功能(或系统的用途)的描述;
参与者是指可能使用用例的人或外部系统。
两者的关系是“谁使用了哪个用例”。
8.3 案例
《网上图书销售系统》功能需求
1. 查询图书信息:顾客登录该系统后,可根据书名对所需的图书信息进行查询。
2. 订购图书:顾客查询到所需图书后,可制作图书订单。
3. 维护订单信息:顾客可根据需要增加、删除个人订购的图书,及时更新订单信息。
4. 维护个人信息:顾客可随时查询个人信息资料,并更新。
5. 处理顾客订单:图书网站的工作人员收到顾客订单后,对订单及时做出处理,包括:查询顾客订单、查询库存、接受订单并更新库存或拒绝接受顾客订单。
查询顾客订单:从所有订单记录中查询当前未被处理的订单。
查询库存:了解了顾客所需图书后,立即查询该图书的库存。
接受订单并更新库存:库存中尚有该图书,工作人员便可接受顾客订单,并修改库存数量。
拒绝接受顾客订单:库存中若没有该图书,则拒绝接受顾客订单。
6. 查询图书的销售记录:图书网站的管理人员可查询近期图书的销售记录,为今后新书的采购和经营决策提供依据。
7. 维护员工信息:管理人员可对公司所有员工的基本信息进行查询、添加、删除和更新。
8. 采购新书:管理人员根据近期图书的销量情况采购新的图书。
9. 更新图书信息:对原有图书信息及时更新,删除无用图书信息。