摘要类图(Class Diagram)可能是用得最多的一种UML图。类图的基本语法并不复杂,你可能最多学习两三天就可以掌握,然而要真正做到活用类图则可能需要几年的功力。类图是锻炼面向对象分析(OOA:Object-Oriented Analysis)和面向对象设计(OOD:Object-Oriented Design)思想的重要的工具,是业务结构建模的重要工具。本章将会有大量的实战练习,你的OOA思想将会接受极大的考验和提升。

本文全长1万6千多字,并且有几十张插图,由于篇幅过长特分为上、下两篇发出。
本文来自新书《活用UML——需求分析高手》的第3章。

作者:张传波
www.umlonline.org

大纲

上篇:
3.1 面向过程与面向对象
3.2 类图的基础知识
3.3 类之间的关系
3.4 演练类之间的关系

下篇:
3.5 类的“递归”关系与“三角”关系
3.6 考试管理系统——类图综合训练
3.7 关于对象图
3.8 小结与练习

 

如果你还没有阅读上篇,请先阅读!

上篇链接:http://www.cnblogs.com/umlonline/archive/2011/10/17/2215850.html

 

3.5 类的“递归”关系与“三角”关系

 

这个小节是类图的进阶知识,有一点难度,但这些知识在需求分析工作中非常实用。

“递归”关系

我在以前公司面试过的人数可能有数百人,如果面试者说他懂类图,那么我几乎100%会问这个问题:Windows操作系统中有文件夹与文件,请你用类图表达出文件夹与文件的关系。
经过前面的学习,你已经具备了能画出这个图的基本知识了,请你不要看后面的参考答案,先自己尝试完成这个题目。
很多面试者很快就会画出这样的图:


图 1.30  文件夹与文件关系1

我会接着问这些问题:
1)文件夹里面也可以有文件夹啊,这个怎样表示出来?
2)里面的文件夹里面也可能有文件夹,咋办?
很多面试者傻眼了,只有很少数人可以画出来。
其实画不出来也不用灰心,我刚学习类图时,也被这个题目一下子难倒了,后来看到参考答案后恍然大悟,同时对类图产生一种莫名的敬仰!


图 1.31  文件夹与文件关系2

文件夹里面有文件夹,里面的文件夹里面有可能有文件夹,这可能是无穷无尽的“递归”啊!而这个包含关系可以自己指向自己,可以“自包含”,这个无穷“递归”的问题就解决了,实在太完美了!
无论是弱包含还是强包含,都可以“自包含”。除了“自包含”可以形成“递归”,其实直线关系同样是可以指向自己的,这个叫“自关联”,这样也形成了“递归”关系。请看下图:


图 1.32  自关联

这种“递归”结构,一旦展开就会形成一棵树型的结构。需求分析时如果发现树型的业务结构,你可以考虑使用“自包含”或者“自关联”来分析。
其实“自包含”、“自关联”的说法是不严谨的,只是方便记忆和理解,实际上具体的一个文件夹是不会包含自己的。这里我们需要进一步理解类图中的每一个类所代表的意义,一个类并不是指具体的一个业务对象,一个类泛指属于这个类的任意一个业务对象。这里的解释可能还不够清楚,你可以暂且放下,在对象图的小节我们再具体说这个问题。

“三角”关系

前面有个练习,要求你画出公司与雇员的关系,现在要求你分别列出公司和雇员至少3个关键属性。
待你列出关键属性后,请你思考这些问题:
1)薪金是雇员的关键属性吗?合同期、职位呢?
2)公司与雇员,这两者的关系在法律上是如何确立的?
你一定会想到,公司与雇员要签署劳动合同,而劳动合同上会有薪金、合同期、职位这些重要的内容,那么薪金、合同期、职位还算是雇员的属性吗?公司、雇员、劳动合同这三者是怎样的关系?


图 1.33  公司、雇员、劳动合同的关系1

在表示公司与雇员的关系的直线上,拉出一条虚线,虚线另外一端连接劳动合同类,这样的类叫做关联类(Association Class),关联类是对两个类的关系的进一步约束。
最开始你可能会认为薪金、职位、合同期这些似乎应该是雇员的属性,但现在你应该认识到,这些三个关键内容应该体现在公司与雇员的关系上,这些内容应该体现在劳动合同上。再进一步思考,雇员的薪金、职位、合同期是会变化的,你可能会跟同一个公司签署多份劳动合同,也可能签署一份劳动合同后又有多次合同变更。

要识别出能表征两个类关系的关联类,难度是有点高的,有这样的一些实践建议供你参考:
1)如果觉得两个类有关系,则先拉上一条直线再说。
2)如果觉得两个类有关系,但怎样画都觉得这个关系不太合适,那么可以思考是不是漏了一个关联类了。
3)分别列出这两个类的关键属性,思考这些属性的属性值是不是由该类本身就可以确定了。例如:如果我们最开始将薪金作为员工的属性,那么你可以思考薪金的具体数字,是不是员工自己本身可以确定的?你会发现薪金其实是由公司和员工商定后确定的,并不是员工自己本身可以决定。
4)通过对属性的思考,可能会发现这个属性应该是属于另外一个类的,思考这个类是不是能表征原来两个类关系的关联类。

关联类这样复杂的东西,客户是不太可能直接告诉你的,你需要在需求分析中发现和提炼出关联类,这对需求的理解以及项目后期的设计工作将会有很大的帮助。
将薪金、职位、合同期这些信息直接当成是雇员的属性也不是不可以的,这跟我们做系统的目标很有关系。如果我们只是做很简单的员工信息管理,可能就没有必要将合同提炼出来。如果我们要做一个人事管理系统,甚至要产品化,这样就需要我们将业务模型分析得更加透彻。

回到前面的“公司的组织架构”练习,如果我们要做一个通用的公司管理系统,我们希望能尽量适应不同的公司情况,那么例子中所做的对公司组织架构的提炼是很必要的,如果我们能看清楚公司部门架构的本质,那么就能尽量多的适应不同的情况。
我实践建议是:在需求分析阶段应尽量对业务分析得透彻一点,这样后期工作将会更加主动。业务需求模型最终变成设计模型时,我们可以把握设计的“度”的,可以做出弹性很高的设计,也可以做一个比较“老土”的设计。
公司、雇员、劳动合同的关系,其实还可以画成下面这样:


图 1.34  公司、雇员、劳动合同的关系2

这个图可能最体现它们的“三角”关系了,关联类也可以表达成这样的方式。但我在实际工作还是以关联类的方式来表达,我觉得关联类的表达方式更加贴切和专业一点。
在具体的需求分析工作时,如果你发现三个类形成了类似该图的“三角”关系,你可以思考其中一个类是不是可能是关联类,但要注意并不是凡是出现了“三角”关系就一定会有关联类。

怎么样?本节的难度已经更上一城楼了!
类图的最大魅力在于帮助你发掘和提炼业务模型,其他的非UML图可能是做不到的。当然真正要做好发掘和提炼,还是需要你的深厚功力了!

下小节,你将要完成一个综合练习,应用你所学习到的全部类图知识。

 

3.6 考试管理系统——类图综合训练

 

做这综合练习有以下几个目的:
1)让你巩固所学到的类图知识。
2)演练用类图分析需求的基本步骤。
3)学习一些提炼类的新知识。

本练习我们将会演练类图分析需求的基本步骤:
1)识别出类。
2)识别出类的主要属性。
3)描绘出类之间的关系。
4)对各类进行分析、抽象、整理。

本综合训练的题目如下:
某学校打算做一套考试管理系统,当前情况如下:
1)讲师会讲很多门课,大部分的课程需要安排一次考试,有些就不需要。
2)考试题目由讲师出。
3)学生需要参加很多考试,每门考试都有成绩。

请你思考:
1)考试是一个类吗?如果是,考试这个类代表怎样的意思?
2)分析出与考试直接相关的类都有哪些?
3)考试类与其他类是怎样的关系?

本系统围绕考试开展,我们首先要确定考试是怎样的一个类,考试类代表考试试卷吗?还是代表考试这个事情?这是考试管理系统,不是考试试卷管理系统(当然试卷也需要在本系统中管理),需要对考试这个事情进行管理,所以考试类代表的是考试这个事情。
需求分析中遇到的人、物、概念识别为类,这是比较容易做到的,而对于事情,例如考试,我们就不一定能将其识别为类。因为普遍认为,类代表的是一些静态东西,而事情是动态的,不适合用类来表示。这并不是绝对的,由系统的目标出发,有时候我们需要将某些事情、动作等动态内容,识别为类。当我们做某某管理系统,而某某是指某个事情时,其实最终系统是通过管理该事情的记录来实现对该事情的管理。例如:考试管理系统,其实最终系统管理的是考试记录;请假管理系统,其实系统最终管理的是请假记录。为了能让这些事情能被管理,将这些事情识别为类是很必要的。

考试类的意义基本确定了,它的属性有考试时间、地点等内容,现在要思考与考试直接相关的类有哪一些呢? 课程、试卷、讲师、成绩、学生这些合适吗?
请你先列出与考试直接相关的类,并尝试画出它们与考试的关系,然后才继续往下看。
请注意只需要找出与考试直接相关的类就可以了,不需要找间接相关的,另外只需要画出其他类与考试的关系就可以了,至于其他类之间的关系暂不用考虑。


图 1.35  考试类与其他类的关系

说明:此图并没有画出课程、讲师、学生之间的关系,此图重点表达的是其他类与考试类的关系。

此图表达了这样的情况:
1)每个课程要么安排一次考试,要么没有考试,而每个考试只对应一门课程。
2)一名讲师作为出题者对应零到多次考试,而每一次考试必有对应的一位出题的老师。
3)一名学生需要参加零到多次的考试,而每个考试有一到多个学生参加。
至于成绩和试卷,要重点说明一下。

作为一名学生,他参加一门考试就会得到一个成绩,他参加多门考试就得到多门成绩,于是就可以计算出该名学生的平均分、最高分、分数排名等,这些内容可以列为学生的属性。
作为考试来说,一次考试有很多学生参加,这样这门考试就会产生很多个成绩,根据这些成绩,我们可以算出这次考试的平均分、最高分、优秀率、合格率等等,注意平均分、最高分这些也可以叫做这次考试的成绩,这些内容可以列为考试的属性。
学生的分数排名、考试的优秀率这些东西如果列为属性,这些属性可以成为“导出属性”,意思就是通过其他基础数据算出来的属性。需求分析时,我们要重点识别基础属性,基础属性是指“原生”的属性,不根据其他东西计算出来,而是直接得到的。

图3.35中所定义的成绩类是指一名学生参加一次考试所得到的成绩,这个成绩是原生的,通过这个成绩,系统可以从考试的角度或者从学生的角度导出很多其他统计数据。
理解了成绩这个类,应该就比较容易理解试卷这个类了。一次考试对应一名出题老师,老师为这次考试设计了一份题目,这份题目就是试卷。

上述只是参考答案,这个题目并没有标准答案,识别出怎样的类以及画出类之间的关系,从不同的角度就会有不同的结果,关键还是要从系统的目标出发,做出合适的分析。如果你的答案与参加答案很不一致,不代表你画得不好,只要你能有条理地解释这些类和它们的关系,就是合适的!

通过这个综合训练的过程(而不是结果),总结以下几点实践建议供你参考:
1)从系统的目标出发来思考问题。
2)用类图分析需求的基本步骤:识别类、识别属性、画出关系、整理和提炼,只是大致的参考步骤,并不是绝对的。
3)识别类的关键属性,能让我们思考类是否合适,尝试画出类的关系也会让我们再次思考这些类是否合适。
4)多读图,从两个方向来读两个类的关系,能帮助你发现更多问题。
5)只需要表达出的类直接关系就可以了。例如:A和B有关系,B和C有关系,这样其实A和C也是有关系的,它们有间接关系,间接关系不需要直接画出来,只需要画出所有的直接关系,我们可以通过类图的关系网络看到类之间的间接关系。
6)不要试图用一个类图表达所有的内容。考试系统这个题目其实已经简化不少了,实际系统的类图可能有几十个甚至上百个类,要规划好用多个类图来表达不同的内容,每个类图有不同的表达重点。
7)注意识别“原生”的内容,并且根据这些“原生”内容能导出什么“导出内容”,不要将“导出内容”当成“原生内容”的。
8)识别关联类是难点也是关键点,分离出关联类会让我们更加看清楚事务的本质。
9)没所谓绝对正确的答案,关键是要有自己的合理分析,逐步求精、持续优化你的想法。
10)多练习、多讨论,逐步增强你的面向对象分析素养。

 

3.7 关于对象图

 

写过代码的朋友比较容易理解什么是对象,类(class)的实例(instance)就是对象(object)。第1章大话UML曾讲解过对象图,我们再来复习一下。
这是Person类:


图 1.36  Person类

下面这句代码将Person类实例化为person对象:
Person person = new Person();
用对象图表示为:


图 1.37  person对象

一个公司包含多个员工,用类图这样表示:


图 1.38  公司和员工的关系

此图的公司和员工并没有指具体是哪个公司或者哪个员工,如果某公司A有甲、乙、丙三位员工,用对象图则可以这样表示:


图 1.39  公司A与员工甲、乙、丙的关系

“A:公司”表示对象A是公司这个类的实例;如果是“:公司”,则表示这是公司这个类的实例,但没有给出这个实例的具体名称。
类是某一类东西的抽象或者叫统称,而对象则是具体的一个东西,A公司如果有1000名员工,那么就需要画一千个“包含”才能表示出A公司与所有员工的关系。对象与对象之间如果有关系,那肯定是一对一的关系,因为两者都是具体的东西,不可能存在第二个。比方说张三和李四是好朋友,他们的关系就是一对一的好朋友关系,因为不可能再有另外一个张三或者李四,但如果我们将张三和李四抽象为人时,一个人可以与很多人交朋友,这样就可以建立多对多的朋友关系。
需求分析时,其实我们接触到的是一个个具体的东西,如:见到一个个具体的人,接触到一份份具体的业务数据等等,这些具体的东西其实就是对象。而我们分析需求不能就事论事,我们需要将这些对象提炼为类,这样的分析才更具有代表性。我们软件系统并不是用来解决具体某次事件中的一个问题,而是希望能解决某一类问题。
在我的工作经历看来,需求分析工作中很少需要用到对象图。我基本不会使用对象图,而直接使用类图,在少数需要使用对象图时,我甚至会直接用类图代替,这样做也并没有不妥而且也容易理解和解决问题。

前面有一个练习,让你用类图画出你和你的另外一半的关系,其实准确地说你和你的另外一半已经是很具体的一个人了,应该用对象图来表达,但我觉得将其“混淆”为类图也没有什么不妥,而且更简单易懂。
前面“类的递归关系”小节提到“自包含”“自引用”的问题,“自”的意思并不是指对象自己本身,而是指其他的属于同一个类的实例。

对象图就简单介绍到这里,如果你对类图还不是很熟悉的话,建议你对象图了解到这样的程度就可以了。

 

3.8 小结与练习

 

类图是最常用的UML图,是用来训练你OOA思想的最好武器。类图的语法不算很难,要看懂类图难度不大,但要用好类图就相当不容易了。
本章一开始,专门对开发人员进行了“洗脑”,端正你对面向过程和面向对象的认识。如果你不是开发人员,那么这个“洗脑”就可以免了。
接下来你学习了一大堆类图的基本语法,并做了很多练习,你还记得下面列出来的内容吗?


表 3.1 类图基本语法

你还学习了类图的“递归”关系与“三角”关系。


图 3.40  “递归”关系示例


图 3.41  “三角”关系示例

一个个的练习除了让你巩固学到的类图知识,更重要的是通过具体的实例让你体会用类图分析问题的思路和方法。
类图分析需求的基本步骤:
1)识别出类。
2)识别出类的主要属性。
3)描绘出类之间的关系。
4)对各类进行分析、抽象、整理。

类实例化后就是对象,表达这些对象及对象关系的图,就是对象图。需求分析中很少需要使用对象图。
多思考、多练习、多讨论、多总结,不断锻炼和提升你的面向对象分析能力吧!

练习

1.一辆小车有4个轮子,请用类图表示出来。
2.一辆货车也有4个轮子,但货车的前轮和后轮不太一样,用类图如何表示?
3.请用类图表示项目组的人员组成。 提示:请思考项目组包含怎样的角色?项目组架构是树形架构还是网络架构?
4.你要设计一个论坛,请用类图表达出分区、版块、子版块、帖子等论坛常见元素的关系。
5.请在你做过或者正在做的项目中挑选一个,用类图来分析该项目的需求或者部分需求。

 

作者:张传波
www.umlonline.org

 

---全文到此结束---