摘要:类图(Class Diagram)可能是用得最多的一种UML图。类图的基本语法并不复杂,你可能最多学习两三天就可以掌握,然而要真正做到活用类图则可能需要几年的功力。类图是锻炼面向对象分析(OOA:Object-Oriented Analysis)和面向对象设计(OOD:Object-Oriented Design)思想的重要的工具,是业务结构建模的重要工具。本章将会有大量的实战练习,你的OOA思想将会接受极大的考验和提升。
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图可能是做不到的。当然真正要做好发掘和提炼,还是需要你的深厚功力了!
下小节,你将要完成一个综合练习,应用你所学习到的全部类图知识。