291 lines
12 KiB
Markdown
291 lines
12 KiB
Markdown
# 第8章 包图
|
||
|
||
> **考试重要度**:★★
|
||
> **核心内容**:包的概念与可见性、包之间的依赖与泛化关系、四大设计原则
|
||
|
||
---
|
||
|
||
## 📢 从文件夹理解包图
|
||
|
||
💬 你电脑上肯定有文件夹(目录),用来把相关文件放在一起。
|
||
|
||
在UML中,**包**就是"文件夹"——把关系密切的类、接口、组件等放在一起。
|
||
|
||
```
|
||
┌─────────────────┐
|
||
│ 包名 │
|
||
│ ┌───────────┐ │
|
||
│ │ + 公开类 │ │ ← 被import后外部可用
|
||
│ │ # 受保护 │ │ ← 只有子包可用
|
||
│ │ - 私有类 │ │ ← 只有包内部可用
|
||
│ └───────────┘ │
|
||
└─────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 💡 一、包的可见性
|
||
|
||
跟类的可见性一样,包中的元素也有三种可见性:
|
||
|
||
| 可见性 | 符号 | 含义 |
|
||
|--------|------|------|
|
||
| **公有** | `+` | 任何导入此包的包都可以用 |
|
||
| **受保护** | `#` | 只有子包可以用 |
|
||
| **私有** | `-` | 只有包内部可以用 |
|
||
|
||
---
|
||
|
||
## 💡 二、包之间的关系
|
||
|
||
### 1. 依赖关系
|
||
|
||
> 包A中的某个类依赖于包B中的某个类 → 包A依赖于包B。
|
||
|
||
⚠️ **注意**:包之间的依赖关系**没有传递性**!A依赖B,B依赖C,不等于A依赖C。
|
||
|
||
### 2. 泛化关系
|
||
|
||
> 子包继承父包中可见性为public和protected的元素。
|
||
|
||
### 📌 包图各元素的画法速查
|
||
|
||
> 这一节把包图里所有的画图元素(包本身、依赖、泛化)用字符画列出来。
|
||
|
||
#### ① 包的两种画法
|
||
|
||
**标准文件夹画法**(最常用):
|
||
|
||
```
|
||
┌──────────────┐
|
||
│ UI层 │ ← 上方有"小标签"(像文件夹的舌头)
|
||
└──────────────┘
|
||
```
|
||
|
||
字符画表示(小标签在左上角):
|
||
|
||
```
|
||
┌────────────┐
|
||
│┌─┐ │
|
||
││ │ │
|
||
│└─┘─────────┤
|
||
│ UI层 │
|
||
│ │
|
||
│ ┌─────────┐ │
|
||
│ │ 登录页 │ │ ← 包内可以嵌套子包或类
|
||
│ └─────────┘ │
|
||
└─────────────┘
|
||
```
|
||
|
||
**简化画法**(只用矩形):
|
||
|
||
```
|
||
┌──────────────┐
|
||
│ UI层 │
|
||
│ ┌────────┐ │
|
||
│ │ 登录页 │ │
|
||
│ └────────┘ │
|
||
│ ┌────────┐ │
|
||
│ │ 主页面 │ │
|
||
│ └────────┘ │
|
||
└──────────────┘
|
||
```
|
||
|
||
#### ② 包的嵌套
|
||
|
||
```
|
||
┌──────────────────────┐
|
||
│ 电子商务系统 │
|
||
│ ┌──────────┐ │
|
||
│ │ 用户模块 │ │
|
||
│ │ ┌──────┐ │ │
|
||
│ │ │登录类│ │ │
|
||
│ │ └──────┘ │ │
|
||
│ │ ┌──────┐ │ │
|
||
│ │ │注册类│ │ │
|
||
│ │ └──────┘ │ │
|
||
│ └──────────┘ │
|
||
│ ┌──────────┐ │
|
||
│ │ 订单模块 │ │
|
||
│ └──────────┘ │
|
||
└──────────────────────┘
|
||
```
|
||
|
||
#### ③ 包的可见性符号
|
||
|
||
```
|
||
┌────────────────┐
|
||
│ ┌─┐ │
|
||
│ │+│ 公开类 │ ← + 公有:任何外部包都可用
|
||
│ └─┘───────────┤
|
||
│ ┌─┐ │
|
||
│ │#│ 受保护类 │ ← # 受保护:只有子包可用
|
||
│ └─┘───────────┤
|
||
│ ┌─┐ │
|
||
│ │-│ 私有类 │ ← - 私有:只有包内部可用
|
||
│ └─┘───────────┤
|
||
│ │
|
||
└────────────────┘
|
||
```
|
||
|
||
#### ④ 包之间的依赖关系 —— 虚线 + 开放箭头
|
||
|
||
> 一个包中的类**引用**另一个包中的类 → 包之间形成依赖。
|
||
|
||
```
|
||
┌──────────────┐ ┌──────────────┐
|
||
│ UI层 │ │ 业务层 │
|
||
│ │ │ │
|
||
│ ┌────────┐ │ │ ┌────────┐ │
|
||
│ │登录窗口 │ │ │ │登录服务 │ │
|
||
│ └────────┘ │ │ └────────┘ │
|
||
│ │ │ │
|
||
└──────────────┘ └──────────────┘
|
||
│ ▲
|
||
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┘
|
||
虚线 + 开放箭头
|
||
(依赖方向:UI层 依赖 业务层)
|
||
```
|
||
|
||
⚠️ **依赖方向**:箭头从"使用者"指向"被使用者"(类似类图里的依赖)。
|
||
|
||
#### ⑤ 包之间的泛化关系 —— 实线 + 空心三角
|
||
|
||
> 子包继承父包的内容。子包继承父包中**public 和 protected** 的元素。
|
||
|
||
```
|
||
┌──────────────┐ ┌──────────────┐
|
||
│ 业务层 │ │ 通用层 │
|
||
│ (子包) │ ─ ─ ─ ─ ─ ─ ─ ▷ │ (父包) │
|
||
│ │ 空心三角 │ │
|
||
│ ┌────────┐ │ │ ┌────────┐ │
|
||
│ │订单处理 │ │ │ │日志工具 │ │
|
||
│ └────────┘ │ │ └────────┘ │
|
||
│ ┌────────┐ │ │ ┌────────┐ │
|
||
│ │支付处理 │ │ │ │通用工具 │ │
|
||
│ └────────┘ │ │ └────────┘ │
|
||
└──────────────┘ └──────────────┘
|
||
```
|
||
|
||
⚠️ **泛化方向**:空心三角**指向父包**(与类图泛化一致)。
|
||
|
||
#### ⑥ 完整包图示例
|
||
|
||
```
|
||
┌────────────────┐
|
||
│ 表现层 │
|
||
│ ┌────────┐ │
|
||
│ │登录页 │ │
|
||
│ └────────┘ │
|
||
│ ┌────────┐ │
|
||
│ │主窗体 │ │
|
||
│ └────────┘ │
|
||
└───────┬────────┘
|
||
│ 依赖
|
||
╌ ╌ ╌ ╌ ╌ ╌ ╌
|
||
▼
|
||
┌────────────────┐ ▷ ┌────────────────┐
|
||
│ 业务层 │ ─ ─ ─ ─ ─ ─ ─ ─ ─│ 通用层 │
|
||
│ │ 泛化 │ │
|
||
│ ┌────────┐ │ │ ┌────────┐ │
|
||
│ │登录管理 │ │ │ │日志工具 │ │
|
||
│ └────────┘ │ │ └────────┘ │
|
||
│ ┌────────┐ │ │ ┌────────┐ │
|
||
│ │订单管理 │ │ │ │数据校验 │ │
|
||
│ └────────┘ │ │ └────────┘ │
|
||
└───────┬────────┘ └────────────────┘
|
||
│ 依赖
|
||
╌ ╌ ╌ ╌ ╌ ╌ ╌
|
||
▼
|
||
┌────────────────┐
|
||
│ 数据层 │
|
||
│ ┌────────┐ │
|
||
│ │用户DAO │ │
|
||
│ └────────┘ │
|
||
│ ┌────────┐ │
|
||
│ │订单DAO │ │
|
||
│ └────────┘ │
|
||
└────────────────┘
|
||
```
|
||
|
||
🔑 **一句话记忆口诀**:包用文件夹画,标签是包名;包间依赖是虚线开放箭头(指向被依赖),包间泛化是实线空心三角(指向父包);包可以嵌套,元素分+/-可见性。
|
||
|
||
---
|
||
|
||
## 💡 三、包的四大设计原则
|
||
|
||
这些原则告诉你**怎么把类分到不同的包里**:
|
||
|
||
### 1. 重用等价原则(REP)
|
||
|
||
> 把可以一起复用的类放在一个包中。包 = 可重用的单元。
|
||
|
||
💬 就像一个工具包——扳手和螺丝刀放在一起,因为它们总是一起用。
|
||
|
||
### 2. 共同闭包原则(CCP)
|
||
|
||
> 把需要同时修改的类放在一个包中。
|
||
|
||
💬 修改了类A就必须修改类B?那它们应该在一个包里——改一个包就够了。
|
||
|
||
### 3. 共同重用原则(CRP)
|
||
|
||
> 不会一起用的类不要放在同一个包里。
|
||
|
||
💬 别把厨房用品和修车工具放一起——要用厨房用品的人不需要修车工具。
|
||
|
||
### 4. 非循环依赖原则(ADP)
|
||
|
||
> 包之间的依赖关系**不能形成环**。
|
||
|
||
💬 A→B→C→A 这样的循环依赖会严重妨碍复用。破解方法:提取共同接口或拆分包。
|
||
|
||
### 🔑 核心目标:高内聚、低耦合
|
||
|
||
| 原则 | 作用 |
|
||
|------|------|
|
||
| **高内聚** | 包内的类关系紧密(REP + CCP) |
|
||
| **低耦合** | 包之间的依赖尽量少(CRP + ADP) |
|
||
|
||
---
|
||
|
||
## ✍️ 边学边练
|
||
|
||
**题目**:判断以下做法是否合理。
|
||
|
||
1. 把订单处理类和用户登录类放在同一个包
|
||
2. A包依赖B包,B包依赖C包,C包依赖A包
|
||
3. 把所有工具类放在一个util包中,让其他包依赖它
|
||
4. 把用户界面类、数据库访问类、业务逻辑类放在同一个包
|
||
|
||
**答案:**
|
||
1. ❌ 不合理 — 违反CRP(不会一起使用的类不要放一起)。订单处理的人不需要登录功能。
|
||
2. ❌ 不合理 — 违反ADP(循环依赖)。
|
||
3. ✅ 合理 — 符合REP(工具类作为可重用单元)。
|
||
4. ❌ 不合理 — 违反CCP和CRP。不同层次的类(界面/数据/逻辑)修改原因不同,应该分开。
|
||
|
||
⚠️ **实用建议**:通常按层次分包(UI层、业务层、数据层),而不是按功能分包。
|
||
|
||
---
|
||
|
||
## 📝 章末自测
|
||
|
||
**1. 填空题**
|
||
- 包的四大设计原则缩写是:( ___ )( ___ )、( ___ )( ___ )、( ___ )( ___ )、( ___ )( ___ )
|
||
- ADP原则要求包之间的依赖不能形成( ___ )( ___ )
|
||
- 包中元素的三种可见性是:公有(( ___ )( ___ ))、受保护(( ___ )( ___ ))、私有(( ___ )( ___ ))
|
||
|
||
**2. 简答题**
|
||
- 简述REP和CRP之间的矛盾是什么?
|
||
- 包图和组件图的关系是什么?
|
||
|
||
**答案:**
|
||
**填空题**:REP、CCP、CRP、ADP;循环;+、#、-
|
||
|
||
**简答题**:
|
||
- REP说要把可一起复用的类放在一个包,这可能导致一个包很大(包含所有可能用到的类);CRP说不会一起用的类要分开,这可能导致很多小包。两者需要权衡。
|
||
- 包存放组件,组件包含类。包相当于文件夹,组件相当于文件。部署时:类→组件→包→结点。
|
||
|
||
---
|
||
> 🔗 上一篇:[第7章 组件图与部署图](第07章-组件图与部署图.md) | 下一篇:[第9章 数据建模](第09章-数据建模.md)
|