学过Java编程的都知道什么是Package,Package在Java编程语言中是一种包机制,这种包机制可以把若干个程序模块或包(在Java语言中,单个的程序模块也称为类)组织起来,构成一个具有层次结构的子系统。Package实际上对应了系统的层次结构。

UML的包图模型类似Package结构,不同的是UML包图模型仅描述Package高层次的模块间关系,对于较低层的模块一般不涉及,这些较低层的模块一般通过设计类图来描述。UML包图属于高层设计模型。

当我们使用包图模型设计一个复杂系统时。首先要将系统进行功能分解,把一个大的系统划分为多个子系统。然后将整个系统作为一个包,划分的子系统作为子包放置在系统包内,包允许多层嵌套,建议最多两层,嵌套多层的包会增加较多的编码工作量,系统架构也会变得复杂。下图是图书馆借书系统的包图模型。

 

JUC包架构 java包结构图_Java

图 1 图书馆借书系统的包图模型

 

在包图中主要使用两个符号。

一个是带标题的矩形框,它表示主系统或子系统(也可以说主包或分包),标题填入主系统或子系统的名称,最外层的方框是主系统,子系统被放置在主系统方框之内,表示这些子系统是主系统的一部分。

一个是带箭头的虚线,表示包与包之间存在依赖关系,箭头的尾部表示被依赖的包,而头部是独立的包。例如在上图中,读者管理子系统需要通过图书管理子系统获取可借阅的图书,同时又需要从系统维护子系统中获取登录读者的权限,因此读者管理子系统依赖于图书管理子系统和系统维护子系统。另外,图书管理子系统也依赖于系统维护子系统。

包的依赖性表示一个包中的结构或代码依赖于另一个包。例如读者管理子系统在查询可借阅图书时,会调用图书管理子系统的图书查询方法获取图书列表信息。包之间的依赖关系会导致被依赖包的代码发生变动时,依赖包也要进行相应地修改。

那么我们如何判断两个子系统之间存在依赖关系呢?我们来看生活中的一个场景。

假设一个人赚了很多钱,他想把赚来的钱存到银行,他需要到银行把这笔钱存上。注意这时这个存钱的人就和银行产生了关系,他需要银行帮他把钱存起来,还能赚取利息。很显然这个人的存钱行为需要银行的协助来完成,也可以说这个人的存钱行为依赖于银行。这就是人和银行的依赖关系,人要存钱赚取利息就会依赖于银行。

 

JUC包架构 java包结构图_Java_02

图 2人的存钱行为依赖于银行

我们再来看一个空调系统的例子。空调对温度的调节依靠两个子系统,一个子系统是温度控制子系统,一个子系统是空调启动控制子系统。温度控制子系统用于感知周围环境的温度,根据用户设置的温度情况,向空调启动控制子系统发出启动或关闭空调的指令,从而调节空调周围的环境温度。因此说温度控制子系统和空调启动控制子系统是存在依赖关系的,空调启动控制子系统依赖于温度控制子系统,因为它需要等待温度控制器发出的启动和关闭信号。

 

JUC包架构 java包结构图_UML_03

图 3 空调系统的温控原理图

上图是空调系统的温控原理图,从图中可以看出,空调启动控制子系统依赖于温度控制子系统,它需要等待温度控制子系统发出的信号。下图是绘制的该系统的包图。

 

JUC包架构 java包结构图_依赖关系_04

图 4 空调温控系统包图

现在我们结合前面学过的包图的知识,来绘制人脉项目系统包图。包图可以使用Visio工具的UML静态结构图来绘制,包图的主要图形符号见下表。

 

JUC包架构 java包结构图_依赖关系_05

系统分析员和系统设计师根据人脉系统的前期调研,把人脉系统划分为用户子系统、名片子系统和数据库子系统三个子系统。下图是绘制的系统包图。

 

JUC包架构 java包结构图_依赖关系_06

图 5 人脉系统包图

在上面的包图中,名片子系统和用户子系统是依赖于数据库子系统的,因为它们都需要从数据库中存取数据。名片子系统也依赖于用户子系统,因为它需要从用户子系统中获取用户的信息,并与名片数据关联起来。

包图是UML建模语言用于从较高层次描述系统结构的模型。在实际的系统设计中,如果已经绘制了系统结构图和系统流程图,可以不用绘制包图。包图的优势在于可以和Java编程语言的Package对应起来,再结合详细的设计类图,可以提供很好的代码自动生成机制。