手把手教你画 UML 类图

类(接口)的表示

类的表示

在 UML 类图中,一个矩形代表一个类,如图:

>

矩形分为三部分:

第一部分为类名,如果用正体书写,说明这是可以实例化的普通类;如果用斜体书写,说明这是抽象类。

第二部分为该类的属性,书写格式为:
1
可见性 属性名 : 属性类型

可见性有以下几种:

可见性 说明
+ public
- private
# protected

第三部分为该类的方法,书写格式为:

1
可见性 方法名(参数名1 : 参数类型1, ...) : 方法返回值类型

例子

假设有这样一个 Person 类:

1
2
3
4
5
6
7
8
public class Person {
private String mName;
private int mAge;

public void doSomething() {

}
}

那么它的类图如下:

接口的表示

和类的表示类似,接口也是用矩形表示,并且该矩形也由三部分组成。和类不同的是,第一部分需要在接口名的上方加上 <> 修饰符。如图:

例子

例如有个 Vehicle 接口:

1
2
3
4
public interface Vehicle {
String name();
void move();
}

它的类图如下:

关系

类与类(接口)间共有六种关系,下面对每种关系进行分析:

继承关系

继承关系表示父类和子类间的关系,它的符号(空心三角形 + 实线)为:

由子类指向父类,即子类 -> 父类

假如有一个 Student 类继承于 Person 类:

1
2
3
4
5
6
7
8
9
10
11
12
public class Person {
protected String name;
protected int age;

public void say() {}
}

public class Student extends Person {
private String mNumber;

public void study() {}
}

用类图表示如下:

接口关系

接口关系表示类和接口之间的关系,它的符号(空心三角形 + 虚线)为:

由类指向接口,即类 -> 接口

假如有一个 Car 类实现了 Vehicle 接口:

1
2
3
4
5
6
7
8
9
10
11
12
public interface Vehicle {
void move();
}

public class Car implements Vehicle {
private String mName;

@Override
public void move() {

}
}

用类图表示如下:

关联关系

关联关系表示一个类内部拥有另一个类,可分为以下三种:

  1. 单向关联

单向关联指类 A 的内部拥有类 B,但类 B 的内部没有类 A,它的符号(实线箭头)为:

例如教室内部含有桌子:

1
2
3
4
5
6
public class Classroom {
private List<Desk> mDesks;
}

public class Desk {
}

用类图表示如下:

  1. 双向关联

双向关联指类 A 的内部拥有类 B,并且类 B 的内部拥有类 A,它的符号(实线)为:

例如老师会带多个学生,而每个学生都有带他的老师:

1
2
3
4
5
6
7
public class Teacher {
private List<Student> mStudents;
}

public class Student {
private Teacher mTeacher;
}

用类图表示如下:

  1. 自关联

自关联指类 A 的内部拥有类 A(自己),它的符号和单向关联一样,不过它指向的是自己。

例如在单链表中,每个节点内部都指向下一节点:

1
2
3
public class Node {
private Node mNext;
}

用类图表示如下:

聚合关系

聚合关系是单向关联的一种。在这种关系中,一般是整体对象拥有个体对象。它的符号(空心菱形 + 实线)为:

其中菱形那头连着整体对象,另一头连着个体对象。

整体对象和个体对象的生命周期不同,整体不存在了,个体依然存在。例如 Team 拥有 Person,当 Team 解散了,Person 并不会消失,它还可以加入其它的 Team。

在代码中实现聚合关系时,通常将个体对象通过构造方法的参数注入到整体对象中:

1
2
3
4
5
6
7
public class Team {
private List<Person> mPersonList;

public Team(List<Person> mPersonList) {
this.mPersonList = mPersonList;
}
}

用类图表示如下:

组合关系

组合关系也是单向关联的一种。和聚合关系类似,一般是整体对象拥有个体对象。它的符号(实心菱形 + 实线)为:

其中菱形那头连着整体对象,另一头连着个体对象。

和聚合关系不同的是,在组合关系中,整体对象和个体对象的生命周期一致,整体消亡时个体也会跟着消亡。例如 Person 由 Head、Body、Hand、Leg 等组成,当 Person 消亡时,其组成成分也跟着消亡。

在代码中实现组合关系时,通常在构造方法内部创建个体对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person {
private Head mHead;
private Body mBody;
private Hand mHand;
private Leg mLeg;

public Person() {
mHead = new Head();
mBody = new Body();
mHand = new Hand();
mLeg = new Leg();
}
}

用类图表示如下:

依赖关系

在依赖关系中,存在着依赖方和被依赖方。它的符号(虚线箭头)为:

其中箭头指向被依赖方

假设类 A 和类 B 之间存在依赖关系,类 A 依赖于类 B,那么类 A 为依赖方,类 B 为被依赖方。类 B 的变化将会影响类 A,是一种 “use-a” 关系。

通常被依赖方只是以依赖方的局部变量方法参数静态方法调用等形式存在,而不会作为依赖方的成员。

例如 Person 依赖于 Car:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Person {
// 局部变量
public void drive() {
Car car = new Car();
// ...
}
}


public class Person {
// 方法参数
public void drive(Car car) {
// ...
}
}

public class Person {
// 静态方法调用
public void drive() {
Car.drive();
}
}

用类图表示如下:

小结

  • 继承关系和接口关系比较容易理解,A extends B 就表示 A,B 之间有继承关系,A implements B 就表示 A,B 之间有接口关系
  • 关联关系和依赖关系的不同:关联关系是一种 “has-a” 关系,A 拥有 B 时,B 作为 A 的成员存在。而依赖关系是一种 “use-a” 关系,A 依赖 B 时,B 不作为 A 的成员变量,而是以 A 的局部变量、方法参数、静态方法调用等方式存在。
  • 聚合关系和组合关系都可以看作是一种单向关联。它们之间的不同在于:在聚合关系中,假设 A 拥有 B,则 B 一般是作为构造方法的参数传入,A 和 B 的生命周期不同,A 消亡时 B 还会存在。而在组合关系中,假设 A 拥有 B,则 B 一般是在构造方法内部创建,A 和 B 的生命周期相同,A 消亡时 B 也会跟着消亡。

参考

-------------    本文到此结束  感谢您的阅读    -------------
0%