设计模式之——UML 类图学习

前言

UML 图有很多种,一般掌握类图、用例图、时序图的使用,就能完成大部分的工作。其中,类图主要显示系统中的类、接口以及它们之间的静态结构和关系的一种静态模型。

类的 UML 展示

UML 类一般由三部分组成:

  1. 类名
  2. 类的属性
  3. 类的操作

一个具体类的示例:

具体类

抽象类、接口的表示法

  • 抽象类:类名以及抽象方法都用斜体字表示
  • 接口:在类图中的第一层顶端用构造型<<interface>>表示,下面是接口的名字。此外,还有一种表示方法,就是类上面的一根棒棒糖(圆圈+实线),圆圈旁为接口名称。

接口示例:

接口

类的属性

属性表示方式:

1
可见性 名称:类型[=默认值]

可见性

  • public : 用 + 表示
  • protected: 用 # 表示
  • defult : 无符号表示
  • private : 用 - 表示

类的操作/方法

操作表示方式:

1
可见性 名称([参数列表])[:返回类型]

其中:

  • 参数列表的表示,语法和属性的定义相似,参数个数是任意的,多个参数之间用 , 隔开
  • 返回类型是一个可选项,可以是基本数据类型,也可以是用户自定义类型,还可以是空类型(void)。如果是构造方法,则无返回类型。

类之间的关系

关联关系 associtaion

用于表示一类对象与另一类对象之间有联系。在 Java 中,通常将一个类的对象作为另一个类的成员变量,比如汽车和轮胎。

在 UML 类图中,用直线连接有关联关系的对象所对应的类。

双向关联

关联关系默认不强调方向,表示对象之间互相知道。—— 两个类中,互相有对方类型的成员变量。

单向关联

如果特别强调方向,就加上箭头。比如是 A -> B,则表示 A 知道 B,但 B 不知道 A。—— A 类中有 B 类型的成员变量,而 B 中则没有 A 类型的成员变量。

单向关联

自关联

类的属性对象类型为该类本身。比如。树节点的左右子节点的类型依然是树节点。

自关联

聚合关系(aggregation)

has a 的关系,表示整体与部分的关系。成员对象是整体对象的一部分,但是成员对象可以脱离整体对象独立存在的。部分可以属于多个整体对象,也可以为多个整体对象共享,所以,聚合关系也称为共享关系。例如,公司部门与员工的关系,汽车和发动机的关系。在 UML 中,聚合关系用空心菱形的直线表示(空心菱形在整体的一方,箭头指向部分一方)。在代码实现聚合关系时,成员对象通常作为构造方法、Setter 方法或业务方法的参数注入到整体对象中。

聚合关系

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
public class  Car {
private Engine e;
// 构造注入
public Car(Engine e) {
this.e = e;
}

// 设值注入
public void setEngine(Engine e) {
this.e = e;
}
}

组合关系(composition)

contains a 的关系,它同样也表示整体与部分的关系,但是组合关系中,整体对象可以控制成员变量的生命周期(皮之不存毛将焉附)。例如人的头和嘴巴。在 UML 中,组合关系用实心菱形的直线表示(实心菱形在整体的一方,箭头指向部分一方)。在代码实现组合关系时,通常在整体类的构造方法中,直接实例化成员类。

组合关系

`java
public class Head {
private Mouth mouth;

public Head() {
    // 实例化成员类
    mouth = new Mouth();
}
……

}

依赖关系 dependency

依赖关系是一种使用关系,在需要表示一个事物需要使用另一个事物时使用依赖关系。在大多数情况,依赖关系体现在某个类的方法使用另一个类的对象作为参数。

在 UML 中,依赖关系使用带箭头的虚线表示,由依赖的一方指向被依赖的一方。例如,驾驶员开车,在 Driver 类的 drive() 方法中,将 Car 类型的对象 car 作为一个参数传递,以便在 drive() 方法中能够调用 Car 类的 move()方法,且驾驶员的 drive() 方法依赖车的 move() 方法,因此类 Driver 依赖类 Car

实际系统开发阶段,依赖关系通常有 3 种方式来实现:

  1. 最常见的就是将一个类的对象作为另一个类中方法的参数
  2. 在一个类的方法中将另一个类的对象作为其局部变量
  3. 在一个类的方法中调用另一个类的静态方法

依赖

泛化关系 generalization

泛化关系也就是继承关系,用于描述父类和子类之间的关系,其中,父类又被称为基类或超类。如果对象 A 和对象 B 之间的 is a 关系成立,那么二者之间就存在继承关系。例如,一个年薪制员工 is a 员工,那么,年薪制员工 Salary 对象和员工 Employee 对象之间存在继承关系,Employee 是父对象,Salary 对象是子对象。

在 UML 中,泛化关系用带空心三角形的直线来表示。

在代码实现时,使用面向对象的继承机制来实现泛化关系。Java 语言中使用 extends 关键字来实现继承。例如,Student 类和 Teacher 类都是 Person 的子类。

继承

接口与实现关系 realization

在接口中,通常没有属性,而且,所有的操作都是抽象的,只有操作的声明,没有操作的实现(Java 8 开始,接口里面可以使用 default 关键字给方法增加操作的实现)。

接口之间也可以有与类之间关系的继承关系和依赖关系,但是,接口和类之间还存在一种实现关系

在 UML 中,类与接口之间的实现关系用空心三角形的虚线来表示。例如,定义了一个交通工具接口 Vehicle,包含一个抽象操作 move(),在类 Ship 和 Car 中,都实现了该 move() 操作。在 Java 语言中,使用 implements 关键字。

接口与实现

总结

类图中的关系

参考

  • 看懂UML类图和时序图
  • 知乎/30分钟学会UML类图
Michael翔 wechat
ヾノ≧∀≦)o 欢迎订阅公众号「Coder魔法院」☑工具控 ☑编程 ☑读书☑电影
「🤓 码字不易,来杯Coffee👇」