之前有了解和使用UML,但是从未深入研究和学习UML语言规范。本文将标准学习资料以个人的理解做一个整理,不一定全对,如有错漏还请大家多指教。
1、UML是什么
UML的全称是Unified Modeling Language,通行翻译为:统一建模语言。
这个名字听起来比较抽象,为什么看起来只是一个又一个的矩形和连接线组成的图形,怎么就是一种语言了呢?我的理解是,语言是人类思想传递的一个载体,语言广义上可以有肢体语言、文字语言、图形语言、表情语言。所以只要有一套共同认可的体系,能够用来传递和表达思想,那么这个体系就可以称之为一套语言。比如:肢体语言,点头表达肯定,摇头表达否定。我们的象形文字,用象形的绘画来表示事物,最后简化成了今天的文字。那么UML也一样,只不过传递思想的载体是图形+连接线构成,也是一种语言体系。
2、UML的分类
UML有很多种图,但大体上可分为“结构型”和“行为型”两类图。
结构型图描述的是某种结构,这种结构在某段时间段内应该是稳定的、静态的;
行为型图描述的是某种行为,是动态的;
(1)结构型的图(Structure Diagram)
类图(Class Diagram)
对象图(Object Diagram)
构图(Component Diagram
部署图(Deployment Diagram)
包图(Package Diagram)
(2)行为型的图(Behavior Diagram)
活动图(Activity Diagram)
状态机图(State Machine Diagram)
顺序图(Sequence Diagram)
通信图(Communication Diagram)
用例图(Use Case Diagram )
时序图(Timing Diagram)
以上并非所有UML图,但是常用和常见的图,基本全列出来了。UML的图很多,本文主要目的是讲清楚其中的“类图”。
选择“类图”是因为我认为在UML中最常用的图多属于行为型图,而行为型图的学习门槛相对较低,描述难度相对较低,哪怕不使用标准的UML规范,凭借自己的经验也可以使用其他方法很好的表述和传达。但结构型的图不同,一般需要结构型图描述的事情中会包含较多的抽象概念,表述和理解的门槛相对较高,没有一定的共同认知很难做到准确的传达和理解。因此学习UML的语言规范就显得更具有价值,学习性价比也高。因此先拿“类图”开刀。
1、什么是类
首先我们需要引入一个概念:属性。
根据字典的释义: 一个事物有许许多多的性质与关系, 我们把一个事物的性质与关系,都叫做事物的属性。 由于事物属性的相同或相异,客观世界中就形成了许多不同的事物类。
具有相同属性的事物就形成一类,具有不同属性的事物就分别的形成不同的类。
简单来说,类就是由相同属性的事物形成的统称。
举例:“水果”是一个类。
根据常识,我们都知道,苹果、橘子、香蕉都属于水果。因为这几个食物都是含水分较多的植物果实。
奇怪的是这个世界上没有任何一个具体事物叫做水果。 那我们是如何总结出他们都是水果的呢?
人们发现苹果、橘子、香蕉都具有“含水分较多”、“食物”、“植物果实”的相同属性。人们为了方便识别和了解这些具有相同属性的事物,就将共同属性抽象出来,以此分类,并给这个“类”起了一个名字,称之为:水果。
按照我的理解(仅供参考),类就是一个或多个事物的抽象出的共有特征的集合。
2、什么是类图
这是一个只有一个类的类图。一个类就是一个矩形框,由类名、属性(Attribute)、操作(Operation)组成。
前面的“+”号表示这个属性/操作是 public 类型的,“-”号表示private类型。一般情况下,在进行初始分分析阶段,直接标示为“+”即可。
冒号后面的 int,表示属性的类型是 int 型,即整数型。在需求分析初始阶段,可不必标识属性的类型。
拿刚才的水果举例,如果画成类图:
画成类图其实非常简单,但是如何在实际应用中抽象出合适的、具有实际价值的类和属性是比较难,需要反复推敲思考的部分。
( 比如将这篇文章的读者进行分类,用类图识别出读者有哪些类,这些类又有什么关键属性。ps: 可以思考一下, 答案在文末 。)
一个类图通常会有多个类,多个类之间会存在不同的关系,下边介绍一下类之间的关系如何表达。
3、类与类之间的关系
- 下图为重点表达类之间的关系,只画出名字,省略了属性和操作。
3.1 关联关系
(1)做软件需求分析时,如果觉得两个业务概念之间有联系,但暂时不能确定具体是怎样的,那么就先画一条线将两者连起来再说。随着对业务的理解,这条线条会进一步具体化,可以为这条线添加更多的元素。
(2)C、D两个类用一条直线相连,但在直线两端各有一个数字1,表示一个C对应一个D
(3)表示一个E对应0到多个F,*号的意思就是表示0到多个。
(4)还可以可以在线条的两端标记两者分别是处在怎样的角色。上图表示I和J之间有关系,在这个关系中1的身份是上司,J的身份是下属。
(5)完整表达一个上司对应多个下属关系的类图
(6)这个图表示由A可找到B,箭头表示方向,由A可“导航”到B。写代码时,如果A类有一个成员变量保存的是类 B 的引用,也就是说由类A 可以找到类 B。
通俗来讲,就是在A类属性中,包含了B类的某一个或多个属性,可以通过包含的属性,找到B这个类。比如:
在工作场景下提交请假单时:请假单中会写有请假者的名字、请假时间、请假事由、审批情况等属性。其中的请假者名字同时也是“请假者类“”的一个“名字”属性。在需要时,我们可以通过请假单上的请假者名字,来找到这个请假者的其他信息,比如职位、性别、年龄等。
那么由A可以找到B,就可以用上图的箭头来表示,这个导航关系。
3.2 包含关系
上图表示:一个部门可以有0到多个员工。
有两种表示法,一种是空心菱形,一种是实心菱形。两种菱形表示包含的强烈程度不同,空心菱形是“弱”包含(UML术语称为聚合(Aggregation)),实心菱形则是“强”包含(UML术语称为组合(Composition))。
“弱”包含表示如果部门没有了,员工也可以继续存在;“强”包含表示如果部门没有了,员工也不再存在。
3.3 继承关系
该图为:A泛化为 B。泛化(Generalization)这个词比较难理解,可以理解为抽象、提炼等。
方便点的说法可以称为“继承”关系。既A继承B。表示A 继承了 B,A 具备 B 的特点,同时也有自己特有的特点。
例如西红柿(A)具有水果(B)的特点,但是西红柿又有其自己的特性,可以用来炒菜和烹饪。那么就可以用上图表示。
在泛化关系中,以图3.17 为例,我们有可能先发现 A,然后导出 B,这时可以说由 A 泛化为B;也有可能是先发现 B,然后导出 A,这时可以说 A 继承B。
3.4 依赖关系
人没有食物就不能生存,人对食物有依赖关系。可以用虚线箭头表示依赖(Dependency)关系。依赖程度是相对而言的,不一定是 A 没有 B 就不能“生存”了才是依赖关系。在具体的业务逻辑中,对于某个事情,A 需要 B 来协助才能完成,也是一种依赖。
三、 举例
最后使用苹果、橘子、香蕉的例子画一个类图,来表示这三者的关系。
苹果、橘子、香蕉都是水果的一种,这就是三者的关系。用UML术语说:苹果、橘子、香蕉泛化为水果。
在这个地方,可能有人会疑惑,类是一个抽象概念。水果是一个类可以理解,为什么苹果、香蕉、橘子这么具体的东西也是一个类呢?
其实类泛化的颗粒度是没有固定标准的,具体将什么颗粒度的概念看做一个类要在实际场景下进行考虑。比如我们现在要考虑苹果、香蕉、橘子之间的关系,在当前场景下,那我们就可以把苹果看做一个类。
其实在苹果中还可以分为红富士苹果、红将军苹果、金帅苹果、乔纳金果...等等,不同的品种中还存在着不同属性。如果是要分析红富士苹果和金帅苹果的关系,那么就应该将红富士苹果看成一个类。所以类的颗粒度和层级,看要根据实际情况来考虑。
回过头来看,水果还可以再泛化为食物,食物又可以进一步泛化。一般来说,如果有 A、B、C 等两个或者以上的业务概念,我们发现它们有一些共同的特征,则可以考虑将它们泛化为另外一个东西,这样能帮助我们发现事物的本质:但如果只有一个 A 时,就没有必要对 A 再进行泛化,例如:香蕉、苹果、梨子已经泛化为水果了,而水果则没有必要泛化为食物。当然这只是一般准则,具体要泛化到怎样的层次要看具体的业务分析需要,要靠自己来把握。
[文中思考题]比如将这篇文章的读者进行分类,用类图识别出读者有哪些类,这些类又有什么关键属性。
- 按性别分:男读者、女读者
确实,人无非就是男/女,所以读者不是男生就是女生。这样分类确实是一个方法,但是这样的分类并不合适,这个分析对于我是无意义的。男/女再看本文时可能并不会有明显差异,如此分类后对于我并没有帮助。
- 按职业分:产品经理、程序员、产品运营、其他职业
不同职业的人看这个文章应该是有所差异的,可能其他职业看的一头雾水,而程序员看着又感到很简单嗤之以鼻。不同职业人的认知基础不同,那么如此划分就可以明显感知到,这个文章是为谁而写,应该怎么写,是更通俗易懂还是更加专业。这对我改进或定位是由帮助的。
所以将某类东西归纳在一起,可以称为一个类。类有很多种提炼角度,没有既定规范。但我们需要根据系统的目标、业务的场景等,选取合适的角度对事物进行归纳。
参考资 料:
【1】火球UML大战需求分析
【2】CSIA-UMYP UML中文术语标准v1.0