UML类图是干什么的?UML类图怎么画?为什么别人画的类图清晰明了? UML类图,UML中的一种重要图形,是在面向对象语言用中用来表示一个类。它由两部分组成,类,类之间的关系,可以由下图所示:
ps:聚合关系中,应该是“大雁”聚合于”雁群“,即”大雁“——◇“雁群”
一、什么是UML类图
UML类图(Class Diagram)是统一建模语言(Unified Modeling Language,UML)中最常用的一种静态结构图,用于描述软件系统的类、接口、属性、方法以及它们之间的关系。它是面向对象设计(OOD)的核心工具,帮助开发者可视化系统的结构,明确类之间的协作方式,并为代码实现提供蓝图。
-
核心作用
- 可视化系统结构:通过图形化方式展示类及其关系,便于团队沟通。
- 指导代码实现:直接对应到编程语言中的类、接口、继承等结构。
- 分析需求:在需求阶段帮助识别关键类及其职责。
- 文档化设计:作为系统设计的官方文档,便于维护和扩展。
-
关系描述
关系类型 符号 描述 示例 继承 实线+空心三角箭头 子类继承父类的属性和方法 ElectricCar —▷ Car 实现(接口) 虚线+空心三角箭头 类实现接口中的方法 ElectricCar --▷ Drivable 关联 实线+箭头(可选) 类之间存在使用关系(双向或单向) Driver —> Car 聚合 空心菱形+实线 整体与部分的弱关联(部分可独立存在) Car ◇— Engine 组合 实心菱形+实线 整体与部分的强关联(部分依赖整体) Car ◆— Wheel 依赖 虚线+箭头 类之间临时或偶然的使用关系 Driver --> Car
二、类图详解
2.1 类
类是具有相似结构、行为和关系的一组对象的描述符,是面向对象系统中最重要的构造块。 如下图所示,就表示一个类:
三个格子从上至下分别表示:
- 类名称(如果是接口,就使用斜体表示)
- 类的特性(一般是类的字段和属性,可以没有)
- 类的操作(一般是类的方法或行为)
它们前边的符号有以下几类:
- “+”表示public
- “-”表示private
- “#”表示protected
2.2 类的关系
除了类,类图中还有一个重要元素,即类之间的关系。 根据类的关系的不同,具体可分为6种,分别如下:
2.2.1 继承、泛化关系(用带空心三角形的实线表示)
继承(泛化)关系,它指定了子类如何特化父类的所有特征和行为。例如:鸟是动物的一种,企鹅、鸭、大雁是鸟的一种。
2.2.2 实现(接口)关系(用带空心三角形的虚线表示)
一种类与接口的关系,表示类是接口所有特征和行为的实现。它有两种表示方法:
-
第一种,矩形表示法
- 顶端有
<<interface>> - 第一行:接口名称
- 第二行:接口方法
- 顶端有
-
第二种,棒棒糖表示法
- 圆圈旁为接口名称
- 接口方法在实现类中出现
2.2.3 关联关系(用实箭线表示)
所谓关联关系,就是这个类有一个属性是其他类。
2.2.4 聚合关系(用带空心菱形的实线表示)
聚合关系是关联关系的一种,是强的关联关系;
特点: 部分对象的生命周期并不由整体对象来管理。也就是说,当整体对象已经不存在的时候,部分的对象还是可能继续存在的。比如:一只大雁脱离了雁群,依然是可以继续存活的。
2.2.5 组合关系(用带实心菱形的实线表示)
组合关系同样是关联关系的一种,是比聚合关系还要强的关系。
特点:在组合中,部分与整体生命期一致,部分与组合同时创建并同时消亡 。比如:鸟与翅膀的关系。
2.2.6 依赖关系(用虚箭线表示)
所谓依赖关系,就是构造这个类的时候,需要依赖其他的类,比如:动物依赖水和氧气。如下图所示:
三、举个栗子
3.1 基础类 & 接口定义
// 依赖对象:氧气(无具体逻辑,仅体现依赖关系)
data class Oxygen(
val amount: Int = 21 // 默认氧气含量为 21%
)
// 依赖对象:水(无具体逻辑,仅体现依赖关系)
data class Water(
val amount: Int = 1000 // 默认水量为 1000ml
)
// 关联对象:气候(无具体逻辑,仅体现关联关系)
class Climate(
val weather: String = "天晴" // 默认天气类型为天晴
)
// 组合对象:翅膀(无具体逻辑,仅体现组合关系)
class Wing
// 接口:飞翔(大雁实现该接口)
interface Flyable {
fun fly() // 飞翔行为
}
3.2 抽象父类:动物
/**
* 动物(抽象类,类名非斜体?若 UML 中是抽象类,需加 `abstract`)
* - 属性:有生命(hasLife)
* - 抽象方法:新陈代谢(依赖氧气、水)、繁殖
*/
abstract class Animal {
var hasLife: Boolean = true // 属性:有生命
// 抽象方法:新陈代谢(依赖 Oxygen 和 Water)
abstract fun metabolism(oxygen: Oxygen, water: Water)
// 抽象方法:繁殖
abstract fun reproduce()
}
3.3 子类:鸟(继承动物,组合翅膀)
/**
* 鸟(继承 Animal,组合 Wing)
* - 属性:羽毛(hasFeather)、有角质喙无牙齿(hasBeakNoTeeth)
* - 方法:下蛋(layEgg)
*/
open class Bird : Animal() {
// 组合关系:鸟包含翅膀(生命周期与鸟绑定,构造时初始化)
private val wing = Wing()
var hasFeather: Boolean = true // 属性:羽毛
var hasBeakNoTeeth: Boolean = true // 属性:有角质喙,没有牙齿
override fun metabolism(oxygen: Oxygen, water: Water) {
println("鸟通过翅膀辅助,进行新陈代谢,消耗氧气和水")
}
override fun reproduce() {
layEgg() // 繁殖行为:下蛋
}
open fun layEgg() {
println("鸟下蛋")
}
}
3.4 具体子类:企鹅、鸭、大雁
/**
* 企鹅(继承 Bird,关联 Climate)
* - 关联关系:持有 Climate 引用
*/
class Penguin : Bird() {
var climate: Climate? = null // 关联气候
override fun layEgg() {
println("企鹅在「${climate?.weather ?: "未知"}」气候下下蛋")
}
}
/**
* 鸭(继承 Bird,开放给唐老鸭继承)
*/
open class Duck : Bird() {
override fun layEgg() {
println("鸭下蛋")
}
}
/**
* 大雁(继承 Bird,实现 Flyable 接口)
*/
class WildGoose : Bird(), Flyable {
override fun fly() {
println("大雁展开翅膀,振翅高飞")
}
override fun layEgg() {
println("大雁下蛋")
}
}
3.5 特殊子类:唐老鸭(继承鸭)
/**
* 唐老鸭(继承 Duck,扩展讲话能力)
*/
class DonaldDuck : Duck() {
fun speak() {
println("唐老鸭讲话:好啦好啦~")
}
}
3.6 聚合类:雁群(包含大雁)
/**
* 雁群(聚合 WildGoose,大雁可独立存在)
*/
class WildGooseFlock {
private val geese = mutableListOf<WildGoose>() // 聚合大雁
fun addGoose(goose: WildGoose) {
geese.add(goose)
}
fun flyInVFormation() {
println("雁群以 V 形飞行,共 ${geese.size} 只大雁参与")
}
fun flyInLineFormation() {
println("雁群以一形飞行,共 ${geese.size} 只大雁参与")
}
}
3.7 测试主函数
fun main() {
// 1. 初始化依赖/关联对象
val oxygen = Oxygen()
val water = Water()
val climate = Climate()
// 2. 测试「鸟」的行为
val bird = Bird()
bird.metabolism(oxygen, water) // 新陈代谢
bird.reproduce() // 繁殖(下蛋)
// 3. 测试「企鹅」(关联气候)
val penguin = Penguin()
penguin.climate = climate // 关联气候
penguin.metabolism(oxygen, water)
penguin.reproduce()
// 4. 测试「鸭」和「唐老鸭」
val duck = Duck()
duck.metabolism(oxygen, water)
duck.reproduce()
val donald = DonaldDuck()
donald.metabolism(oxygen, water)
donald.reproduce()
donald.speak() // 唐老鸭讲话
// 5. 测试「大雁」和「雁群」(聚合 + 接口实现)
val goose1 = WildGoose()
val goose2 = WildGoose()
val flock = WildGooseFlock()
flock.addGoose(goose1)
flock.addGoose(goose2)
flock.flyInVFormation() // 雁群 V 形飞行
flock.flyInLineFormation() // 雁群一形飞行
goose1.fly() // 大雁实现 Flyable 接口,调用 fly()
}
3.8 输出结果
3.9 总结 & UML关系验证
| UML 关系 | 代码体现 |
|---|---|
| 继承 | Bird : Animal、Penguin : Bird、Duck : Bird、DonaldDuck : Duck |
| 实现 | WildGoose : Flyable |
| 组合 | Bird 内部持有 private val wing = Wing()(生命周期绑定) |
| 聚合 | WildGooseFlock 持有 MutableList(大雁可独立存在) |
| 依赖 | Animal.metabolism(oxygen: Oxygen, water: Water)(参数依赖) |
| 关联 | Penguin.climate: Climate?(持有 Climate 引用) |