Files
obsidian/软件需求分析/各章笔记/第04章-类图与对象图.md

476 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第4章 类图与对象图
> **考试重要度**:★★★★★
> **核心内容**:类与对象的识别、六大类关系、抽象类与接口、边界类/控制类/实体类
---
## 📢 从生活中理解类和对象
💬 **类 = 模板,对象 = 具体的东西。**
| 概念 | 生活例子 | 代码例子 |
|------|----------|----------|
| **类** | "汽车"这个类别 | `class Car` |
| **对象** | 你家楼下停的那辆红色宝马 | `Car myCar = new Car()` |
| **属性** | 颜色、车牌号、排量 | `color`, `plateNumber` |
| **操作** | 启动、加速、刹车 | `start()`, `accelerate()` |
> 例:银行的"账户"类有属性姓名、密码、余额和操作查询余额、存款、取款。张三的账户就是一个具体对象余额是5000元。
---
## 💡 一、类的三格表示法
```
┌──────────────────────┐
│ 类名 │ ← 第一格:类名
├──────────────────────┤
│ -name: String │ ← 第二格:属性
│ -age: int │
│ +count: int │
├──────────────────────┤
│ +getName(): String │ ← 第三格:操作(方法)
│ +setAge(a: int) │
└──────────────────────┘
```
### 属性语法
```
[可见性] 属性名 [:类型] [=初始值] [{约束}]
```
### 可见性符号
| 符号 | 名称 | 含义 |
|------|------|------|
| `+` | Public公有 | 谁都能访问 |
| `-` | Private私有 | 只能类内部访问 |
| `#` | Protected受保护 | 类内部+子类能访问 |
---
## ✍️ 边学边练(一)
**题目**银行账户类Account有属性账号(私有)、密码(私有)、余额(私有)、利率(公有)。请用UML类图的三格表示法写出。
**答案:**
```
┌──────────────────────┐
│ Account │
├──────────────────────┤
│ -accountNo: String │
│ -password: String │
│ -balance: double │
│ +interestRate: float│
├──────────────────────┤
│ +getBalance():double│
│ +deposit(amt) │
│ +withdraw(amt) │
└──────────────────────┘
```
---
## 💡 二、类之间的六大关系(重中之重!必考!)
### 1. 关联关系Association—— "认识/拥有"
> **含义**:一个类的属性类型是另一个类。这是最基础的关系。
💬 **比喻**:员工"属于"某个部门——Employee类中有一个Department类型的属性。
**关联关系的子类型**
| 子类型 | 说明 | 生存期 | 画法 |
|--------|------|--------|------|
| **普通关联** | 平等关系 | 各自独立 | 实线 |
| **聚合Aggregation** | 整体-部分,弱关系 | 部分可独立存在 | 空心菱形 |
| **组合Composition** | 整体-部分,强关系 | 部分随整体消亡 | 实心菱形 |
💬 **聚合 vs 组合**
- 聚合:学校由学生组成,学校解散了,**学生还在**。
- 组合:汽车由发动机组成,汽车报废了,**发动机也没意义了**。
### 2. 依赖关系Dependency—— "临时使用"
> **含义**:一个类的方法的参数/返回值/局部变量用了另一个类。
💬 **比喻**:你去商店买东西——你跟商店的关系只在买东西那一刻存在,买完就没关系了。
### 3. 泛化关系Generalization—— "是……的一种"
> **含义**:子类继承父类的属性和方法。
💬 **比喻**:狗是动物的一种——狗继承了动物的所有特征,还有自己特有的"汪汪叫"。
### 4. 实现关系Realization—— "履行接口约定"
> **含义**:类实现了接口中定义的所有方法。
### 关联 vs 依赖 对比
| 维度 | 关联 | 依赖 |
|------|------|------|
| **强度** | 强,长期稳定 | 弱,临时短暂 |
| **代码体现** | 属性类型是另一个类 | 方法参数/局部变量用了另一个类 |
| **生命周期** | 对象存在就有关系 | 方法调用结束关系就结束 |
| **画法** | 实线 | 虚线箭头 |
---
## ✍️ 边学边练(二)
**题目**:判断以下场景属于什么关系。
1. 飞机由机翼、发动机、机身组成。(飞机-机翼)
2. 医生在医院工作。(医生-医院)
3. 学生是人。(学生-人)
4. 程序员写代码时用到开发工具。(程序员-开发工具)
**答案:**
1. **组合关系**(实心菱形)—— 机翼不能脱离飞机独立存在
2. **关联关系**(普通关联)—— 医生有"所属医院"这个属性
3. **泛化关系**(继承)—— 学生是人的子类
4. **依赖关系**(虚线箭头)—— 程序员"写代码"这个方法用到了开发工具,但不是长期持有
⚠️ **易错点**:聚合和组合都表示"整体-部分",区别在于部分能否独立存在。能独立=聚合,不能独立=组合。
---
## 💡 三、关联关系的重要概念
### 多重性
| 表示法 | 含义 |
|--------|------|
| `1` | 恰好1个 |
| `0..1` | 0个或1个 |
| `0..*``*` | 0个或多个 |
| `1..*` | 至少1个 |
| `n..m` | n到m个 |
> 例:一个学生选**0..\***门课,一门课被**1..\***个学生选。
### 关联类
> 当一个属性放在哪个类都不合适时,就用关联类。
💬 例:员工和公司之间有个"合同"——合同有"工资"属性。工资既不是员工的固有属性(换公司会变),也不是公司的固有属性。所以"合同"是一个关联类。
### 限定关联
> 用限定符把多对多变成一对多,提高查询效率。
💬 例:一个人可以在多家银行开户(多对多)。但如果限定"在某家银行",就变成一对多了。
---
## 💡 四、抽象类 vs 接口
| 维度 | 抽象类 | 接口 |
|------|--------|------|
| **属性** | 可以有 | 不能有 |
| **方法实现** | 部分方法有实现 | 所有方法都没有实现 |
| **关系** | 子类继承(泛化) | 类实现(实现关系) |
| **多重性** | 只能继承一个 | 可以实现多个 |
| **关键词** | `abstract class` | `interface` |
💬 **比喻**:抽象类像"半成品家具"(有些部分做好了,有些需要你自己完成);接口像"插座标准"(只规定了插孔形状和电压,具体怎么发电不管)。
---
## 💡 五、版型:边界类、控制类、实体类
这是MVC模式的UML体现期中考试经常考
| 版型 | 职责 | 常见形式 | 对应MVC |
| ---------------------- | ------ | --------- | ---------- |
| **边界类** `<<boundary>>` | 与外界交互 | 窗口、对话框、报表 | View |
| **控制类** `<<control>>` | 协调业务逻辑 | 处理业务规则 | Controller |
| **实体类** `<<entity>>` | 持久化数据 | 数据库表对应的类 | Model |
🔑 **协作关系**:边界类接收用户输入 → 控制类处理业务逻辑 → 实体类存取数据。
---
## 📌 附录:类图常用画图符号速查
> 这一节把类图中所有的关系符号、接口、抽象类、版型、对象图等所有画图元素用字符画列出来,画类图时直接照搬即可。
### 1. 关联关系Association—— 实线(可带多重性)
**普通关联**(双向带多重性):
```
┌────────┐ 1 0..* ┌────────┐
│ 老师 │ ────────────────── │ 学生 │
└────────┘ └────────┘
```
**自关联**(一个类关联到自己):
```
┌────────┐
│ 员工 │
│ │
│ 领导 │◀──┐
└────────┘ │
│ │
└─────┘
```
### 2. 聚合关系Aggregation—— 实线 + 空心菱形 ◇
> 部分可脱离整体独立存在。
```
┌────────┐ ┌────────┐
│ 班级 │ ───────────── │ 学生 │
└────────┘ └────────┘
(整体) (部分,可独立)
💬 学校没了,学生还在 —— 所以是空心菱形
```
### 3. 组合关系Composition—— 实线 + 实心菱形 ◆
> 部分不能脱离整体独立存在。
```
┌────────┐ ┌────────┐
│ 汽车 │ ───────────── │ 发动机 │
└────────┘ └────────┘
(整体) (部分,离不开整体)
💬 汽车报废了,发动机也没意义了 —— 所以是实心菱形
```
### 4. 依赖关系Dependency—— 虚线 + 开放箭头
```
┌────────┐ ┌────────┐
│ 司机 │ ─ ─ ─ ─ ─ ─ ─⇨ │ 汽车 │
└────────┘ └────────┘
(使用者) (被使用者)
(虚线 + 开放箭头)
```
### 5. 泛化关系Generalization—— 实线 + 空心三角
**方向**:子类 → 父类(空心三角指向父类)。
```
┌────────┐ ┌────────┐
│ 狗 │ ───────────── │ 动物 │
└────────┘ └────────┘
(子类) (父类)
```
### 6. 实现关系Realization—— 虚线 + 空心三角
**方向**:实现类 → 接口(空心三角指向接口)。
```
┌────────┐ ┌──────────────┐
│ 鸟 │ ─ ─ ─ ─ ─ ─ ─ │<<interface>>│
└────────┘ │ 飞行 │
(实现类) └──────────────┘
(接口)
```
### 7. 接口的两种画法
**普通矩形画法**(在类图中更常见):
```
┌──────────────────┐
│ <<interface>> │ ← 关键字标识
│ 飞行 │ ← 接口名
├──────────────────┤
│ +起飞(): void │ ← 只有声明,没有实现
│ +降落(): void │
└──────────────────┘
```
**棒棒糖表示法**(简化版,常在组件图中使用):
```
┌────────┐ ┌────────┐
│ 鸟 │●─ ─ ─ ─ ─ ─ ─ ─ ─ ┤ 飞行 │ (棒棒糖+连接线)
└────────┘ └────────┘
(实现类) (接口)
```
### 8. 抽象类与抽象方法
> **画法**:抽象类**类名用斜体**、抽象方法**方法名用斜体**。在字符画里用 `<<abstract>>` 标识或加文字说明。
```
┌────────────┐
│ 动物 │ ← 实际画图时类名用斜体
├────────────┤
│ │
├────────────┤
│ 移动() │ ← 实际画图时方法名用斜体
│ 叫() │
└────────────┘
{abstract} ← 标注方式(实际画图用斜体)
```
### 9. 版型Stereotype的画法
**边界类**
```
┌────────────────┐
│ <<boundary>> │ ← 写在类名上方
│ 登录页面 │
├────────────────┤
│ -用户名:String │
│ -密码:String │
├────────────────┤
│ +提交():void │
└────────────────┘
```
**控制类**
```
┌────────────────┐
│ <<control>> │
│ 订单处理 │
├────────────────┤
│ │
├────────────────┤
│ +处理订单() │
│ +检查库存() │
└────────────────┘
```
**实体类**
```
┌────────────────┐
│ <<entity>> │
│ 订单 │
├────────────────┤
│ -订单号:String│
│ -金额:double │
├────────────────┤
│ +保存() │
│ +查询() │
└────────────────┘
```
### 10. 对象图的画法
> 对象名格式:`对象名:类名`(对象名和类名下加**下划线**),属性有具体值。
```
┌─────────────────┐
│ 张三:员工 │ ← 对象名:类名,下划线
├─────────────────┤
│ 员工号 = "E001" │ ← 属性=值
│ 姓名 = "张三" │
│ 年龄 = 28 │
└─────────────────┘
```
**对象图与类图对比**
```
类图(描述规则) 对象图(描述实例)
┌──────────┐ ┌────────────────┐
│ 员工 │ │ 张三:员工 │
├──────────┤ ├────────────────┤
│ -员工号 │ │ 员工号="E001" │
│ -姓名 │ ──> │ 姓名="张三" │
│ -年龄 │ │ 年龄=28 │
├──────────┤ └────────────────┘
│ +查询() │
└──────────┘
```
### 11. 关联类的画法
> 关联类挂在关联线中间,用虚线连到关联线上。
```
┌────────┐ ┌────────┐
│ 员工 │ ─ ─ ─ ─ ─ ─ ─ │ 公司 │
└────────┘ │ └────────┘
┌────────┐
│ 合同 │ ← 关联类(虚线连到关联线上)
├────────┤
│ -工资 │
│ -合同期│
└────────┘
```
🔑 **一句话记忆口诀**:实线实箭是关联,空心菱形是聚合,实心菱形是组合,虚线开放箭头是依赖;实线空三角是泛化(继承),虚线空三角是实现(接口)。
---
## ✍️ 边学边练(三)
**题目**:在线购物系统中,"用户"通过"购物页面"下单,系统"订单处理"模块检查库存后,更新"订单"数据和"库存"数据。请指出各属于哪种版型。
**答案:**
- 购物页面 → **边界类**(与用户交互)
- 订单处理模块 → **控制类**(协调业务逻辑)
- 订单、库存 → **实体类**(持久化的数据)
完整流程:边界类("购物页面") → 控制类("订单处理") → 实体类("订单""库存")
---
## 💡 六、对象图
> **对象图 = 类图的"截图"**。类图描述通用规则,对象图描述某一时刻的具体情况。
| 类图 | 对象图 |
|------|--------|
| 三个格子(类名+属性+操作) | 两个格子(对象名:类名 + 属性值) |
| 描述所有可能的情况 | 描述某一个时刻的快照 |
| 属性定义特征(如"姓名: String" | 属性有具体值(如"姓名 = 张三" |
💬 **比喻**:类图像"菜单"(描述菜的做法),对象图像"上桌的菜"(一份具体的菜)。
---
## 📝 章末自测
**1. 填空题**
- 聚合关系中,整体不存在了,部分( ___ )存在。(能/不能)
- 组合关系中,整体不存在了,部分( ___ )存在。(能/不能)
- 边界类、控制类、实体类分别对应MVC中的 _____ )、( _____ )、( ___
**2. 判断题**
- ( ) 依赖关系比关联关系更弱
- ( ) 接口可以有属性
- ( ) 抽象类可以被实例化
- ( ) 对象图是类图的实例
- ( ) 一个类只能继承一个抽象类,但可以实现多个接口
**3. 分析题**
- 职工类Employee包含属性empcode、name、address、birthday。Address类包含houseNumber、streetNumber、city、zipcode。分析两个类之间的关系。
**答案:**
**填空题**能、不能、View、Controller、Model
**判断题**:✅ ❌(接口无属性) ❌(抽象类不能实例化) ✅ ✅
**分析题****关联关系**。因为Employee类中有一个属性address其类型是Address类。这是一个长期稳定的结构关系。多重性Employee端1Address端0..*(一个地址可以被多个员工使用)。
---
> 🔗 上一篇:[第3章 用例图](第03章-用例图.md) | 下一篇:[第5章 顺序图与协作图](第05章-顺序图与协作图.md)