类图用于静态对象建模,在软件开发的初期常用UML类图来表示类、接口及类之间的关联。这里介绍一下UML类图的基础知识.

UML属性的表示方式

UML的属性有两种表示方式:属性文本和关联线.

属性文本表示属性的完整格式是:

visibility name : type multiplicity = default {property-string}
可见性      属性名: 属性类型              默认值     特性字符串

其中属性的可见性常分为三种, 若没有标志可见性,则默认是私有的:

  • public: +
  • private: -
  • protected: #

属性文本表示属性的例子 ___

关联线表示属性的例子 ___

如上图所示是关联线表示属性的例子,其格式详细描述如下:

  • 导航性箭头由源对象指向目标对象,表示源对象Store的一个属性是目标对象Address
  • 多重性放置在目标对象Address一端
  • 角色名放置在目标对象Address一端,用以表示属性名称address

多重性可用*表示0或者更多,1..*表示1或者更多,1..40表示1-40,3,5,8精确地为3,5,8,等诸如此类的表示方式. 多重性的值表示的是特定时刻有效关联的实例数量,而不是一段时间内有效关联的实例数量.

那么,在表示UML属性时,何时使用属性文本,何时使用关联线呢?通常情况下,对数据类型对象使用属性文本表示法,对其他自定义对象使用关联线. 其中,数据类型对象指的是其唯一标识不具有意义的对象,常见的数据类型都是原始类型,例如: 布尔型、日期、数字、字符、字符串(文本)、时间、地址、颜色、几何形状、电话号码、邮政编码、枚举类型等. 两种表示方法在语义上是等价的,但是在绘制UML类图时,图中展示与另一个类框的关联线能够在视觉上强调图中对象之间的链接. 在代码中,它们归结为同一事物,例如Java代码:

public class Store {
    private int id;
    private String phoneNum;
    private Address address;
    private List<SaleItem> saleItems = new ArrayList<SaleItem>();
    //TODO: operator
}

在上面的代码中,我们看到类Store中还具有一个集合属性saleItems,那么,怎么使用属性文本和关联线表示集合属性呢?

如下图所示,显示了UML类图中表示集合属性的两种方式.

UML中表示集合属性的两种方式 ____

UML注解/操作/方法

UML注解符号显示为摺角矩形,并使用虚线连接到要注解的元素上, 这从上面的图中可以看到.

UML表示操作的语法形式为:

visibility name (parameter-list) : return-type {property-string}

若没有标志其可见性,则默认该操作是公有的. 特性字符串可包含任何附件信息,例如可能产生的异常、操作是否抽象{abstract},等等.

操作不是方法. UML中操作是声明,其中包含名称、参数、返回类型、异常列表、可能的前置和后置条件约束等. 操作不是实现,方法是实现. 在UML类图中,使用构造性为<<method>>的UML注解符号表示方法实现. 如下图所示:

UML类图中表示方法 ____

在绘制UML类图的过程中,通常忽略访问属性的操作(getter&setter),在写构造函数的操作时,可在前加<<constructor>>标识.

关键字

UML关键字是对模型元素分类的文本修饰,常用的UML关键字有:

  • <<actor>>, 类元为参与者,在类图中,置于类元名称之上
  • <<interface>>, 类元为接口,在类图中,置于类元名称之上
  • {abstract}, 抽象元素,不能实例化,在类图中,置于类元名称或者操作名称之后
  • {leaf}, 标识终止类(final class)和不能够被子类复写的操作
  • {ordered}, 具有强制顺序的一组对象,在类图中,置于关联的端点

泛化、依赖、组合

泛化,意为从超类到子类的OOPL继承,用由子类到超类的实线和空心三角箭头表示,如下图所示. 抽象类(abstract class)和操作既可以采用{abstract}标记表示,也可以采用斜体名称来表示. 与之相反,终止类(final class)和不能够被子类复写的操作以{leaf}标记表示.

UML泛化示例 ____

依赖,可以视为耦合的另一个版本,耦合意味着某元素(客户元素)耦合或依赖于另一个元素(提供者元素),使用从客户到提供者的虚线箭头线表示.在类图中,使用依赖线描述对象之间的全局变量、参数变量、局部变量和静态方法(对其他类的静态方法加以调用)的依赖.对于如下Java代码:

public class Sale
{
    public void updatePriceFor(Product product) {
        Money basePrice = product.getPrice();
    }
}

updatePriceFor方法接收参数Product对象作为参数,然后向其发送getPrice消息。由此可见,Sale对象对Product具有参数可见性,并且有发送消息的耦合,因此对Product有依赖,这种依赖在类图中表示为:

UML依赖关系示例 ___

为表示依赖的类型,可以给依赖线附加关键字或者构造型,如<<call>>, <<create>>等.

组合,也称为组成聚合,是一种很强的整体-部分聚合关系,组合关系有以下含义: 1. 在某一时刻,部分的实例(如Finger)只属于一个组成实例(如Hand) 2. 部分必须总是属于组成 3. 组成要负责创建和删除其部分,既可以自己来创建/删除部分,也可以与其他对象协作来创建/删除部分.如果组成被销毁,其部分也必须被销毁.

UML中,用带有实心菱形箭头的关联线来表示组合,箭头指向组成类,如下图所示:

UML组合管理示例 ___

限定关联

限定关联具有限定符,限定符用户从规模较大的相关对象集合中,依据限定符的键选择一个或者多个对象. 一般来说,限定关联暗示了基于键对事物进行查找,如HashMap中的对象.例如,如果ProductCatalog中含有许多Product,并且每个Product中都能够通过itemID来选择,那么使用UML的限定关联的示例如下图所示.

UML限定关联示例 ___

对于限定关联,需要注意的是多重性的变化,限定关联减少了在关联目标端的多重性,通常由多变为一,因为限定关联通常暗示从较大集合中选择一个实例.

关联类

关联类允许将关联本身作为类,并且使用属性、操作和其他特性对齐建模. 例如,如果Company雇佣了许多Person,建模时使用了Employ关联,则可以将关联本身建模为Employment类,并拥有startDate这样的属性. UML中,用从关联到关联类的虚线表示关联类,如下图所示:

UML中的关联类 ___

单实例类

面向对象设计的世界中,有一种极为常见的模式-单实例类(Singleton)模式,其含义是类实例化后只存在一个实例,永远不会有第二个,这就是“单实例类”的实例. 在UML类图中,可以在类框中名称分栏的右上角标记“1”来表示这种类, 如下图所示:

UML单实例类示例 ___

主动类

主动对象(active object)运行于自己控制的执行线程之上,主动对象的类即为主动类(active class). 在UML中,主动类使用左右两边为双竖线的类框来表示,如下图所示:

UML中的主动类 ___