目录
----------------------------------
[1. 类(Class)](#1. 类(Class))
[1.1. 类的成员变量的表示方式](#1.1. 类的成员变量的表示方式)
[1.2. 类的成员方法的表示方式](#1.2. 类的成员方法的表示方式)
[2. 接口(Interface)](#2. 接口(Interface))
[3. 包(Package)](#3. 包(Package))
[1. 关联(Association)](#1. 关联(Association))
[1.1. 单向关联](#1.1. 单向关联)
[1.2. 双向关联](#1.2. 双向关联)
[1.3. 自关联](#1.3. 自关联)
[1.4. 多重性关联](#1.4. 多重性关联)
[2. 聚合(Aggregation)](#2. 聚合(Aggregation))
[3. 组合(Composition)](#3. 组合(Composition))
[4. 依赖(Dependency)](#4. 依赖(Dependency))
[5. 继承(泛化 Generalization)](#5. 继承(泛化 Generalization))
[6. 实现(Realization)](#6. 实现(Realization))
----------------------------------
----------------------------------
----------------------------------
----------------------------------
----------------------------------
学习前言
作者坚定认为,在绘制任何图形之前,都应该先弄清楚图形的概念、组成元素以及绘制规范。
这有助于提升我们的绘图效率。
----------------------------------
讲解一:类图
一、类图的组成结构
1. 类(Class)
类( Class )封装了成员变量( Field )和成员方法( Function / Method ),是面向对象的三大组成部分
之一,它是具有相同成员变量、成员方法、关系的对象集合的总称。
在软件系统运行时,类将被实例化成对象( Object ),对象对应于某个具体的事物,是类的实例(
Instance )。
在 UML 类图中,类使用包含类名、成员变量( Field ) 和成员方法( Function / Method ) 且带有分割
线的矩形来表示,比如下图表示一个Employee 类,它包含 name , age 和 email 这 3 个属性,以
及 modifyInfo() 方法。
1.1. 类的成员变量的表示方式
UML 规定类的成员变量的表示方式为:
可见性 名称:类型 [ = 缺省值 ]
类的成员变量的表示方式的具体实例便如 Employee 类的成员变量:- name:String
。
- **"可见性"**表示该成员变量/成员方法对于类外的元素而言是否可见,包括公有 ( public ) 、私有 ( private ) 和受保护 ( protected ) 三种,在类图中分别用符号 +、- 和 # 表示。若省略这些符号表示具有 package(包)级别的可见性。若成员变量/成员方法具有下划线,表明它是静态的。还记得 Employee 类中的前面带减号 - 的 3 个成员变量和带加号 + 的成员方法吗?这些符号表示了这个成员变量或成员方法的可见性。
- **"名称"**表示成员变量的名称,用一个字符串表示。
- "类型" 表示成员变量的数据类型,可以是基本数据类型,也可以是用户自定义类型。
- "缺省值" 是一个可选项,即属性的初始值。如某个类中的成员变量定义语句 Double pai = 3.1415926; 中的 3.1415926 便是成员变量的缺省值。
1.2. 类的成员方法的表示方式
UML规定类的成员变量的表示方式为:
可见性 名称(参数列表) [ : 返回类型]
类的成员方法的表示方式的具体实例便如Employee类的成员方法:+ modifyInfo():void。
- "可见性" 的定义与成员变量的可见性定义相同。
- "名称" 即成员方法的名称,用一个字符串表示。
- "参数列表" 表示成员方法的参数,其语法与成员方法参数列表的定义相似,参数个数是任意的,多个参数之间用英文逗号","隔开。
- "返回类型" 是一个可选项,表示成员方法的返回值类型,依赖于具体的编程语言,可以是基本数据类型,也可以是用户自定义类型,还可以是空类型( void ),如果是构造方法,则无返回类型。
在下图的 Demo 类中,成员方法 method1 的可见性为 public(+),带入了一个 Object 类型的参数
par,返回值为空类型( void );
成员方法 method2 的可见性为 protected(#),无参数,返回值为 String 类型;操作 method3 的可
见性为 private(-),包含两个参数,其中一个参数为 int 类型,另一个为 int[] 类型,返回值为 int 类
型。
2. 接口(Interface)
Java 接口是一系列成员方法的声明,是一些成员方法特征的集合,一个接口只有成员方法的特征
没有成员方法的实现,因此这些成员方法可以在不同的地方被不同的类实现,而这些实现可以具有
不同的行为(功能)。接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所
组成。接口是解决 Java 无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准
的。或者我们可以直接把接口理解为 100% 的抽象类,既接口中的方法必须全部是抽象方法。
( JAVA8 及之前版本可以这样理解,但 JAVA9 拓展了接口的定义)
在 UML 中,接口既可用下图 Animal 接口左上角类似钥匙的图标 o- 表示,也可由在 UML 的接口
名称附近加上<> 标志来表示。
3. 包(Package)
Java 引入了包( package )机制,提供了类的多层命名空间,用于解决类的命名冲突、类文件管
理等问题。
UML 中的一个包直接对应于 Java 中的一个包,每个包的名称对这个包进行了惟一性的标识。
二、UML类图中类与类之间的关系
整体而言,类和类之间关系包括了 has , use , is 三种关系:
- has 包括了关联 ( Association ) ,聚合 ( Aggregation ) ,组合 ( Composition ) 关系
- use 包括了依赖 ( Dependency ) 关系
- is 包括了继承 ( 泛化 Generalization ),实现 ( Realization ) 关系
1. 关联(Association)
关联 ( Association ) 关系是类与类之间最常用的一种关系,它是一种结构化关系,用于表示一类对
象与另一类对象之间有联系,如汽车和轮胎、师傅和徒弟、班级和学生等等。在 UML 类图中,用
实线连接有关联关系的对象所对应的类,在使用 Java、C# 和 C++ 等编程语言实现关联关系时,
通常将一个类的对象作为另一个类的成员变量。在使用类图表示关联关系时可以在关联线上标注角
色名,一般使用一个表示两者之间关系的动词或者名词表示角色名(有时该名词为实例对象名),
关系的两端代表两种不同的角色,因此在一个关联关系中可以包含两个角色名,角色名不是必须
的,可以根据需要增加,其目的是使类之间的关系更加明确。如在一个登录界面类 LoginForm 中
包含一个 JButton 类型的注册按钮 loginButton ,它们之间可以表示为单向关联关系,代码实现时
可以在 LoginForm 中定义一个名为 loginButton 的属性对象,其类型为 JButton 。
如下图所示:
上述 UML 类图对应的 Java 代码片段如下:
public class LoginForm {
private JButton loginButton; //定义为成员变量
......
}
public class JButton {......}
在 UML 中,关联关系通常又包含如下几种形式:
1.1. 单向关联
类的关联关系可以是单向的,单向关联用由包含者指向被包含者的带箭头的实线表示。
例如:顾客( Customer ) 拥有地址 ( Address ) ,则 Customer 类与 Address 类具有单向关联关
系,
上述 UML 类图对应的 Java 代码片段如下:
public class Customer {
private Address address;
......
}
public class Address {...}
1.2. 双向关联
默认情况下,关联是双向的,双向关联用实线表示。
例如:顾客 ( Customer ) 购买商品 ( Product ) 并拥有商品;反之,卖出的商品总有某个顾客与之
相关联。
因此,Customer 类和 Product 类之间具有双向关联关系,如下图所示:
上述 UML 类图对应的 Java 代码片段如下:
public class Customer {
private Product[] products;
......
}
public class Product {
private Customer customer;
......
}
1.3. 自关联
在系统中可能会存在一些类的属性对象类型为该类本身,这种特殊的关联关系称为自关联。
例如:一个节点类 ( Node ) 的成员又是节点
Node 类型的对象,如下图所示:
上述 UML 类图对应的 Java 代码片段如下:
public class Node {
private Node subNode;
......
}
1.4. 多重性关联
多重性关联关系又称为重数性 ( Multiplicity ) 关联关系,表示两个关联对象在数量上的对应关系。
在 UML 中,对象之间的多重性可以直接在关联直线上用一个数字或一个数字范围表示。
对象之间可以存在多种多重性关联关系,常见的多重性表示方式如下表所示:
|--------|------------------------------------------|
| 表示方式 | 多重性说明 |
| 1...1 | 表示另一个类的一个对象只与该类的一个对象有关系 |
| 0...* | 表示另一个类的一个对象与该类的零个或多个对象有关系 |
| 1...* | 表示另一个类的一个对象与该类的一个或多个对象有关系 |
| 0...1 | 表示另一个类的一个对象没有或只与该类的一个对象有关系 |
| m...n | 表示另一个类的一个对象与该类最少 m,最多 n 个对象有关系 ( m ≤ n ) |
例如:一个界面 ( Form ) 可以拥有零个或多个按钮 ( Button ) ,但是一个按钮只能属于一个界面,
因此,一个Form 类的对象可以与零个或多个 Button 类的对象相关联,但一个 Button 类的对象只
能与一个 Form 类的对象
上述 UML 类图对应的 Java 代码片段如下:
public class Form {
private Button[] buttons; //定义一个集合对象
......
}
public class Button {......}
2. 聚合(Aggregation)
聚合 ( Aggregation ) 关系表示整体与部分的关系。在聚合关系中,成员对象是整体对象的一部
分,但是成员对象可以脱离整体对象独立存在。在 UML 中,聚合关系用由整体指向部分的带空心
菱形和箭头的直线表示。
例如:汽车发动机 ( Engine ) 是汽车 ( Car ) 的组成部分,但是汽车发动机可以独立存在,
因此,汽车和发动机是聚合关系,如下图所示:
在代码实现聚合关系时,成员对象通常作为构造方法、Setter 方法或业务方法的参数注入到整体对
象中,上述UML 类图对应的 Java 代码片段如下:
public class Car {
private Engine engine;
//构造注入
public Car(Engine engine) {
this.engine = engine;
}
//设值注入
public void setEngine(Engine engine) {
this.engine = engine;
}
......
}
public class Engine {......}
3. 组合(Composition)
组合 ( Composition ) 关系也表示类之间整体和部分的关系,但是在组合关系中整体对象可以控制
成员对象的生命周期,一旦整体对象不存在,成员对象也将不存在,成员对象与整体对象之间具有
同生共死的关系。在 UML 中,组合关系用由整体指向部分的带实心菱形和箭头的直线表示。
例如:人的头 ( Head ) 与嘴巴 ( Mouth ) ,嘴巴是头的组成部分之一,而且如果头没了,嘴巴也就
没了,因此头和嘴巴是组合关系,如下图所示:
在代码实现组合关系时,通常在整体类的构造方法中直接实例化成员类,上述 UML 类图对应的
Java 代码片段如下:
public class Head {
private Mouth mouth;
public Head() {
mouth = new Mouth(); //实例化成员类
}
......
}
public class Mouth {......}
4. 依赖(Dependency)
依赖 ( Dependency ) 关系是一种使用关系,特定事物的改变有可能会影响到使用该事物的其他事
物,在需要表示一个事物使用另一个事物时使用依赖关系。大多数情况下,依赖关系体现在某个类
的方法使用另一个类的对象作为参数。
在 UML 中,依赖关系用由依赖者指向被依赖者的带箭头的虚线表示,由依赖的一方指向被依赖的
一方。例如:驾驶员开车,在 Driver 类的 drive() 方法中将 Car 类型的对象car 作为一个参数传
递,以便在 drive() 方法中能够调用 car 的 move() 方法,且驾驶员的 drive() 方法依赖车的 move()
方法,因此类Driver 依赖类 Car,如下图所示:
在系统实施阶段,依赖关系通常通过三种方式来实现:
- 第一种也是最常用的一种方式是如上图所示的在一个类的方法中将另一个类的对象作为其形式参数;
- 第二种方式是在一个类的方法中将另一个类的对象作为其局部变量;
- 第三种方式是在一个类的方法中调用另一个类的静态方法。
上述 UML 类图对应的 Java 代码片段如下:
public class Driver {
public void drive(Car car) {
car.move();
}
......
}
public class Car {
public void move() {
......
}
......
}
5. 继承(泛化 Generalization)
继承 ( 泛化 Generalization )关系用于描述父类与子类之间的关系,父类又称作基类或超类,子类
又称作派生类。
在 UML 中,泛化关系用由继承者指向被继承者的带空心三角形的直线来表示。在代码实现时,我
们使用面向对象的继承机制来实现泛化关系,如在 Java 语言中使用 extends 关键字、在 C++/C#
中使用冒号 " :"来实现。
例如:Student 类和 Teacher 类都是 Person 类的子类,Student 类和 Teacher 类继承了 Person
类的属性和方法,Person 类的属性包含姓名 ( name ) 和年龄 ( age ) ,每一个 Student 和 Teacher
也都具有这两个属性,另外 Student 类增加了属性学号 ( studentNo ),Teacher 类增加了属性教师
编号 ( teacherNo ), Person 类的方法包括行走 move() 和说话 say(),Student 类和 Teacher 类继
承了这两个方法,而且 Student 类还新增方法study(),Teacher 类还新增方法 teach() 。
如下图所示:
上述 UML 类图对应的 Java 代码片段如下:
//父类
public class Person {
protected String name;
protected int age;
public void move() {......}
public void say() {......}
}
//子类
public class Student extends Person {
private String studentNo;
public void study() {......}
}
//子类
public class Teacher extends Person {
private String teacherNo;
public void teach() {......}
}
6. 实现(Realization)
在很多面向对象语言中都引入了接口的概念,如 Java 、C# 等,在接口中,通常没有属性,而且
所有的操作都是
接口之间也可以有与类之间关系类似的继承关系和依赖关系,但是接口和类之间还存在一种实现 (
Realization ) 关系,在这种关系中,类实现了接口,类中的操作实现了接口中所声明的操作。
在 UML 中,类与接口之间的实现关系用由实现者指向被实现者的带空心三角形的虚线来表示。
例如:定义了一个交通工具接口 Vehicle,包含一个抽象操作 move(),在类 Ship 和类 Car 中都实
现了该move() 操作,不过具体的实现细节将会不一样,如下图所示:
实现关系在编程实现时,不同的面向对象语言也提供了不同的语法,如在 Java 语言中使用
implements 关键字,而在 C++/C# 中使用冒号" :"来实现。
上述 UML 类图对应的 Java 代码片段如下:
public interface Vehicle {
public void move();
}
public class Ship implements Vehicle {
public void move() {......}
}
public class Car implements Vehicle {
public void move() {......}
}
c
讲解二:轮廓图
【概念】轮廓图提供了一种通用的扩展机制,用于为特定域和平台定制 UML 模型。
图中我们定义了一个简易的 EJB 的概要图。
Bean 是从 Component 扩展来的。Entity Bean 和 Session Bean 继承了 Bean。
EJB 拥有 Remote 和 Home 接口,和 JAR 包。
----------------------------------
讲解三:组件图
【概念】描绘了系统中组件提供的、需要的接口、端口等,以及它们之间的关系。
【目的】用来展示各个组件之间的依赖关系。
订单系统组件依赖于客户资源库和库存系统组件。中间的虚线箭头表示依赖关系。
另外两个符号,表示组件连接器,一个提供接口,一个需要接口。
----------------------------------
讲解四:组合结构图
【概念】描述了一个"组合结构"的内部结构,以及他们之间的关系。这个"组合结构"可以是系统的
一部分,或者一个整体。
图中描述了 Car 是由车轴连接着的两个前面轮子、两个后面轮子,和引擎组合的。
----------------------------------
讲解五:对象图
【概念】对象图是类图的一个实例,是系统在某个时间点的详细状态的快照。
【目的】用来表示两个或者多个对象之间在某一时刻之间的关系。
图中就是描述的,某时间点 bat 这个公司有一个研发部,一个销售部,两个部门只有一个人
iisheng。
----------------------------------
讲解六:部署图
【概念】描述了系统内部的软件如何分布在不同的节点上。
图中简单的表示,不同机器上面部署的不同软件。
----------------------------------
讲解七:包图
【概念】描绘了系统在包层面上的结构设计。
《Use》关系表示使用依赖,Web Shopping 依赖 Payment
《Merge》关系表示合并,Web Shopping 合并了 Shopping Cart 就拥有了 Shopping Cart 的功能
《Access》关系表示私有引入,比如代码中的指定包名类名
《Import》关系表示公共引入,比如 Java 中的 import 之后,就可以直接使用 import 包中的类
了。