UML 包图 详细介绍

 UML 包图 详细介绍

6.1 包图的概念

包是一种常规用途的组合机制。UML中的一个包直接对应于Java中的一个包,C#中的命名空间。在Java中,一个包可能含有其他包、类或者同时含有这两者。进行建模时,通常使用逻辑性的包,用于对模型进行组织;使用物理性的包,用于转换成系统中的Java包。

C#命名空间与java包的区别分析

本文实例分析了C#命名空间与java包的区别。分享给大家供大家参考。具体分析如下:

相同点:

1、都是为了重用性(reusebility)——软件工程中一个非常重要的目标。

2、C#里面的命名空间和java中的包都属于访问权限的控制机制。

不同点:

1、C#命名空间只是一种逻辑上的结构,它允许所组织的类文件的物理存放位置与逻辑结构不一致,而Java中类文件的物理结构必须与逻辑结构一致。

2、Java的package本身没有子包的概念,所有package都是并列的关系,没有谁包含谁的问题。比如:org.dominoo.action和org.dominoo.action.asl之间绝对没有包与子包的关系。它们是各自独立的包,各自拥有自己的class/interface的集合。在org.dominoo.action.asl的某个java文件里,如果想引用org.dominoo.action里的某个class/interface,则必须import org.dominoo.action。

C++/C#的namespace方案则不然,一个namespace可以有自己的sub-namespace,我们不妨将namespace也称为package,那么C++/C#的package之间就可能存在包与子包的关系.

3、Java中使用import语句而C#中使用using namespace语句。

6.1.1 包图

UML 包图 详细介绍

包图是描述包及其关系的图。与所有UML的其它图一样,包图可以包括注释、约束。包间的关系有依赖关系和泛化关系。上图是一个典型的包图。

6.1.2 包的作用

在面向对象软件开发的过程中,类显然是构建整个系统的基本元素。但是对于大型的软件系统而言,其包含的类将是成百上千,再加上类间的关联关系、多重性等,必然是大大超出了人们对系统的理解和处理能力。为了便于管理这些类,我们引入了“包”这种分组元素。

包的作用是:
1.对语义上相关的元素进行分组。如,把功能相关的用例放在一个包中。
2.提供配置管理单元。如,以包为单位,对软件进行安装和配置。
3.在设计时,提供并行工作的单元。如,在设计阶段,多个设计小组,可以同时对几个相互独立包中的类进行详细设计。
4.提供封装的命名空间,同一个包中,其元素的名称必须惟一。

6.1.3 包中的元素

在包中可以拥有各种其它元素,包括类、接口、构件、节点、协作、用例,甚至是其它子包或图 。一个元素只能属于一个包。

命名方式

每个包必须有一个与其他包相区别的名称,包的名字是一个字符串:

  • 简单名:仅含一个简单的名称。

  • 路径名::以包所位于的外围包的名字作为前缀的包名

    1. 当不需要显示包的内容时,将包的名字放入主方框内;

    2. 需要显示内容时包的名字放入左上角的小方框中,将内容放入主方框内。

    3. 标以 {global} 的包叫通用包,表示系统的所有其他包都依赖于该包。

 

 

UML中,用文件夹符号来表示一个包。包由一个矩形表示,它包含2栏。下面是最常见的几种包的表示法
UML 包图 详细介绍

 

6.2.1 包的名称

每个包必须有一个与其他包相区别的名称。标识包名称的格式有两种:简单名和全名。
其中,简单名仅包含包一个简单的名称;全名是用该包的外围包的名字作为前缀,加上包本身的名字。
例如,Rose常用表示方法中,其包名UI就是一个简单名。而包System.Web.UI才是一个完整带路径的名称,表示UI这个包是位于System.Web命名空间中的。如图所示
UML 包图 详细介绍

6.2.2 包的元素

在一个包中可以拥有各种其他元素,包括类、接口、构件、节点、协作、用例,甚至是其他包或图。这是一种组成关系,意味着元素是在这个包中声明的,因此一个元素只能属于一个包。
每一个包就意味着一个独立的命名空间,因此,两个不同的包,可以具有相同的元素名,但由于所位于的包名不同,因此其全名仍然是不同的。
在包中表拥有的元素时,有两种方法:一种是在第二栏中列出所属元素名,一种是在第二栏中画出所属元素的图形表示(参见下图)。
UML 包图 详细介绍

6.2.3 包元素的可见性

像类中的属性和方法一样,包中的元素也有可见性,包内元素的可见性控制了包外部元素访问包内部元素的权限。
包的可见性有3种:可以用“+”来表示“public”,即,该元素是共有的;用“#”来表示“protected”, 即该元素是保护的,用“-”来表示“private”, 即,该元素是私有的。
UML 包图 详细介绍
包内元素的可见性,标识了外部元素访问包内元素的权限。表6-1列出了可见性与访问权限的关系。

表6-1 可见性与访问权限(假设包B中的元素访问包A中的元素)
UML 包图 详细介绍

6.2.4 包的构造型

为了表示包的新特性,用构造型来描述包的新特征。包的构造型有5种,下面分别说明。
1.《system》构造型:《system》构造型的包表示整个系统.
2.《subsystem》构造型:《subsystem》构造型的包则表示正在建模的系统中某个独立的子系统.
3.《facade》构造型:只是某个其它包的视图,它主要用来为其它一些复杂的包提供简略视图
4.《stub》构造型:是一个代理包,它服务于某个其他包的公共内容,这通常应用于分布式系统的建模中 .
5.《framework》构造型:用来表示一个框架的,框架是一个领域内的应用系统提供可扩充模板的体系结构模式

6.3 包图中的关系

 

包图中的关系有2种:依赖关系、泛化关系。

6.3.1 依赖关系

1.《use》关系
《use》关系是一种默认的依赖关系 ,说明客户包(箭尾端的包)中的元素以某种方式使用提供者包(箭头端的包)的公共元素,也就是说客户包依赖于提供者包。如果没有指明依赖类型,则默认为《USE》关系。
例如在图中,有两个《USE》依赖,Client包将通过Server包来完成Order的存储,而Server包使用System.Data.SqlClient包来实现数据库的存储。
UML 包图 详细介绍

2.《import》关系
《import》关系:最普遍的包依赖类型,说明提供者包的命名空间将被添加到客户包的命名空间中,客户包中的元素也能够访问提供者包的所有公共元素。
《import》关系使命名空间合并,当提供者包中的元素具有与客户包中的元素相同的名称时,将会导致命名空间的冲突。这也意味着,当客户包的元素引用提供者包的元素时,将无需使用全称,只需使用元素名称即可。
例如在上图中,Client包引用了(import)了Rule包,Rule包又引用了GUI包。同时,这还表示Client包间接引用了GUI包。
UML 包图 详细介绍
3.《access》关系
如果只想使用提供者包中的元素,而不想将两个包合并,则应使用该关系。在客户包中必须使用路径名,才能访问提供者包中的所有公共元素。

4.《trace》关系
想表示一个包到另一个包的历史发展,则需要使用《trace》关系来表示

6.3.2 泛化关系

包间的泛化关系类似于类间的泛化关系,使用一般包的地方,可以用特殊包代替。
在系统设计中,对某一个特定的功能,有多种实现方法。例如,实现多数据库支持;实现B/S和C/S双界面。这时就需要定义一些高层次的“抽象包”和实现高层次功能的“实现包”。
在抽象包中定义一些接口和抽象类,在实现包中,定义一些包含实现这些抽象类和接口的具体类。例如在上图中,说明GUI有两种风格:一种是基于WinForm的C/S风格,一种是WebForm的B/S风格。
需要注意的是,在《在UML用户手册》中将其归为泛化关系,而在《UML精粹》中却将其看作是实现关系。

6.4 阅读包图

阅读包图的方法:
1.了解每个包的语义,它包含的元素语义。
2.理解包间的关系。
3.找到依赖关系复杂的包,从最复杂的包开始阅读,然后以此是简单的包。
例如,阅读下面的包图。
UML 包图 详细介绍
对上面包的理解如下:
(1)根据《use》关系可以发现Client包使用Server包,Server包使用System.Data.SqlClient包,根据它们所包含的元素语义,可以得知Client包负责Order(订单)的输入,并通过Server包来管理用户的登录(LoggingService)和数据库存储(DataBase);而Server包还通过.Net的SQL SERVER访问工具包,来实现与数据库的连接和通讯。
(2)看《import》关系,从RULE包所包含的元素语义可知,该包负责处理一些规则,并引用一个具体的窗体(Window);而Client包通过引用RULE来实现整个窗体和表单的显示,输入等,并且还将暂存Order(订单)信息。
(3)接着来看包的泛化关系。GUI有两个具体实现:一个是针对C/S的WindowsGUI,一个是实现B/S的WebGUI.

6.5 创建包图

绘制包图的基本过程主要有三个步骤:第一,寻找包;第二,确定包之间的关系;第三,标出包内元素的可见性。
绘制包图的“最小化系统间的耦合关系”的原则:
最大限度减少包之间的依赖,包封装时,避免包之间的循环依赖;最小化每个包的public、protected元素的个数,最大化每个包中private元素的个数。

6.5.1 寻找包

通过把具有很强语义联系的建模元素分组,找出分析包。分析包必须反映元素的真实的语义分组,而不仅是逻辑架构的理想视图。
我们以对象模型和用例模型为依据,把关系紧密的类分到同一个包中,把关系松散的类分到不同的包中。
1.标识候选包的原则:
(1).把类图中关系紧密的类放到一个包中;
(2).在类继承类层次中,把不同层次的类放在不同的包中。
也可以把用例模型作为包的来源。然而,用例横跨分析包是非常普遍的——一个用例可以由几个不同包中的类实现。

2.调整候选包
在已经识别一组候选包后,然后减少包间依赖,最小化每个包的public、protected元素的个数,最大化每个包中private元素的个数。做法是:
(1).在包间移动类;
(2).添加包或删除包。

良好包结构的关键是包内高内聚,包间低耦合。

通常,当创建分析包模型时,应该尽量使包模型简单。获得正确的包集合比使用诸如包泛化和依赖构造型的特征更加重要,这些特征可以以后再添加,仅当使用诸如包泛化和依赖构造型的特征使得模型更加容易理解时,才使用这些包整理技术。除了保持简单,还应该避免嵌套包。物件在嵌套包结构中埋藏得越深,模型变得越晦涩。

作为经验法则,希望每个包具有4~10个分析类。然而,对于所有的经验法则,却存在例外,如果打破某个法则使得模型更加清晰,就采用这个法则!有时,你必须引入只带有一个或者两个类的包,因为你需要断开包模型中的循环依赖。在这种情况下,这是完全合理的。

6.5.2 消除循环包依赖

应该尽量避免包模型中的循环依赖。如果包A以某种方式依赖包B,并且包B以某种方式依赖包A,就应该合并这两个包,这是消除循环依赖非常有效的方法。但是经常起作用的、更好的方法是,努力分解公共元素成为第三个包C。重新计算依赖关系,以消除循环依赖。示例显示在图中。
很多建模工具允许自动验证包间依赖。如果一个包中的元素访问另一个包中的元素,但两个包间却没有依赖关系,那么工具产生访问冲突列表。
在分析模型中,不可能创建没有访问冲突的包图。
UML 包图 详细介绍

6.6 包图建模

包图主要用于两种不同层次的用途:一是对成组元素建模;二是对体系结构建模。

6.6.1 对成组元素建模

对成组元素进行建模可以说是包图最常见的用途,它将建模元素组织成组,然后对组进行命名,在对成组元素建模时,应遵循以下几个策略:
每个包都应该是由在概念上,语义上相互接近的元素组成。
对于每个包,找出应标记为公共的元素,但应尽可能地少。
一般使用默认的《use》构造型,在实现类时,才用《import》构造型代替《use》构造型。
采用泛化来对特殊包进行建模。
在构建包模型时,注意,在包中只标明对每个包起核心作用的元素;另外业可以标识每个包的文档标记值,以使其更加清晰。

6.6.2 对体系结构建模

体系结构是一个软件系统的核心逻辑结构,常用的体系结构模式包括分层、MVC、管道、黑板、微内核等,而在应用软件中,分层和MVC是最常见的两种结构。
在分层的体系结构中,最常见的划分是表示层(present)、逻辑层(business或domain)、数据层(包括数据访问、日记等)。如果采用分层体系结构,我们就把每一层用一个包来表示,如图所示
UML 包图 详细介绍
图 用包分层

 

UML 包图 详细介绍

上一篇:常见面试题:HashMap的底层原理?


下一篇:Mybatis入门(四) 核心配置文件详解