面向对象与UML
面向对象是以对象作为系统构造的基本单位,通过封装、继承和多态来组织和构建软件系统。
一、面向对象基本概念
1.1 对象与类
| 概念 | 定义 | 关系 |
|---|---|---|
| 类 (Class) | 对具有相同属性和行为的一组对象的抽象描述 | 模板/蓝图 |
| 对象 (Object) | 类的具体实例,拥有类定义的属性和行为 | 实例 |
1.2 封装 (Encapsulation)
定义:将对象的属性(数据)和操作这些属性的方法捆绑在一起,并对外部隐藏内部实现细节。
特点:
- 只通过公共接口(public methods)访问
- 保护数据不被随意修改
- 实现信息隐藏
好处:
- 提高安全性
- 提高模块化程度
- 便于修改和维护
- 促进代码复用
1.3 继承 (Inheritance)
定义:子类(派生类)获取父类(基类)的属性和方法,并可以扩展或修改。
表示关系:is-a(是一种)
示例:狗 is-a 动物
好处:
- 代码复用
- 建立类层次结构
- 支持多态
继承类型:
- 单继承:一个子类只有一个父类
- 多继承:一个子类有多个父类(Java不支持,C++支持)
1.4 多态 (Polymorphism)
定义:不同类的对象对同一消息(方法调用)做出不同的响应。
口诀:一个接口,多种实现
实现方式:
| 方式 | 说明 |
|---|---|
| 方法重写 (Override) | 子类重新定义父类的虚方法 |
| 接口实现 | 不同类实现相同接口 |
| 方法重载 (Overload) | 同一类中同名方法不同参数 |
好处:
- 提高代码灵活性
- 提高可扩展性
- 提高可复用性
1.5 三大特性对比
| 特性 | 核心思想 | 主要作用 |
|---|---|---|
| 封装 | 隐藏细节,暴露接口 | 信息隐藏、安全性 |
| 继承 | 子类复用父类代码 | 代码复用、层次结构 |
| 多态 | 一个接口多种实现 | 灵活性、可扩展性 |
二、UML概述
2.1 什么是UML
UML (Unified Modeling Language):统一建模语言,是一种标准化的可视化建模语言。
用途:
- 描述、规范、构造软件系统
- 为软件开发提供可视化图形
- 帮助团队成员达成共识
2.2 UML图分类
| 类别 | 包含的图 | 关注点 |
|---|---|---|
| 结构图 | 类图、对象图、构件图、部署图 | 系统静态结构 |
| 行为图 | 用例图、活动图、状态图 | 系统动态行为 |
| 交互图 | 序列图、协作图(通信图) | 对象间交互 |
三、常用UML图详解
3.1 用例图 (Use Case Diagram)
用途:从用户角度描述系统功能需求
核心元素
| 元素 | 图形 | 说明 |
|---|---|---|
| 参与者 (Actor) | 🧑 小人图标 | 与系统交互的外部实体 |
| 用例 (Use Case) | ○ 椭圆 | 系统提供的功能 |
| 系统边界 | □ 矩形框 | 系统范围 |
关系类型
| 关系 | 符号 | 说明 | 方向 |
|---|---|---|---|
| 关联 | 实线 | 参与者与用例的联系 | 无方向 |
| 包含 (include) | 虚线箭头 + <<include>> | 基用例必须执行被包含用例 | 基→被包含 |
| 扩展 (extend) | 虚线箭头 + <<extend>> | 可选执行的扩展用例 | 扩展→基 |
| 泛化 | 空心三角箭头 | 继承关系 | 子→父 |
重要区分:
- include:必须执行,如"提交订单"必须"验证登录"
- extend:可选执行,如"查询商品"可选"高级搜索"
示例
┌─────────────────────────────────┐
│ 网上购物系统 │
│ │
顾客 ─┼──── ○ 浏览商品 │
🧑 │ │ │
│ │<<extend>> │
│ ↓ │
│ ○ 高级搜索 │
│ │
顾客 ─┼──── ○ 提交订单 │
🧑 │ │ │
│ │<<include>> │
│ ↓ │
│ ○ 验证登录 │
└─────────────────────────────────┘3.2 类图 (Class Diagram)
用途:描述系统静态结构,显示类、接口及其关系
类的表示
┌────────────────────┐
│ 类名 │ ← 类名(斜体表示抽象类)
├────────────────────┤
│ - 私有属性: 类型 │ ← 属性部分
│ + 公有属性: 类型 │ -私有 +公有 #保护
├────────────────────┤
│ + 公有方法(): 返回值│ ← 方法部分
│ - 私有方法() │
└────────────────────┘类之间的关系
| 关系 | 符号 | 含义 | 强度 |
|---|---|---|---|
| 依赖 | - - -> | 使用关系(参数、局部变量) | 最弱 |
| 关联 | ───── | 结构联系(成员变量) | ↓ |
| 聚合 | ───◇ | 整体-部分,部分可独立存在(has-a) | ↓ |
| 组合 | ───◆ | 整体-部分,部分不可独立(contains-a) | ↓ |
| 泛化 | ───▷ | 继承关系(is-a) | ↓ |
| 实现 | - - ▷ | 实现接口 | 最强 |
聚合 vs 组合:
- 聚合:空心菱形,部分可以独立存在(如班级-学生)
- 组合:实心菱形,部分不能独立存在(如人-心脏)
关系示例
┌──────────┐
│ <<接口>> │
│ IShape │
└────▲─────┘
│ (实现)
┌────────────┴────────────┐
│ │
┌──────┴──────┐ ┌───────┴──────┐
│ Circle │ │ Rectangle │
├─────────────┤ ├──────────────┤
│ - radius │ │ - width │
│ │ │ - height │
├─────────────┤ ├──────────────┤
│ + getArea() │ │ + getArea() │
└─────────────┘ └──────────────┘
↑
│ (依赖)
┌──────┴──────┐
│ Painter │
└─────────────┘
┌─────────┐ ◇────────┌─────────┐
│ 班级 │─────────────│ 学生 │ (聚合)
└─────────┘ └─────────┘
┌─────────┐ ◆────────┌─────────┐
│ 人 │─────────────│ 心脏 │ (组合)
└─────────┘ └─────────┘3.3 序列图 (Sequence Diagram)
用途:描述对象间按时间顺序的消息传递
核心元素
| 元素 | 说明 |
|---|---|
| 对象生命线 | 垂直虚线,表示对象存在时间 |
| 激活 | 生命线上的矩形条,表示对象处于活动状态 |
| 消息 | 对象间的通信,包括同步、异步、返回消息 |
消息类型
| 类型 | 符号 | 说明 |
|---|---|---|
| 同步消息 | ───▶ | 调用方等待返回 |
| 异步消息 | ───> | 调用方不等待 |
| 返回消息 | - - -> | 方法返回 |
| 自关联 | ↺ | 对象调用自己的方法 |
3.4 活动图 (Activity Diagram)
用途:描述系统或业务流程中的活动顺序
核心元素
| 元素 | 符号 | 说明 |
|---|---|---|
| 初始节点 | ● | 流程起点 |
| 终止节点 | ⊙ | 流程终点 |
| 活动 | 圆角矩形 | 具体活动 |
| 判断节点 | ◇ | 条件分支 |
| 合并节点 | ◇ | 分支合并 |
| 分叉 | 粗横线 | 并行开始 |
| 汇合 | 粗横线 | 并行结束 |
| 泳道 | 垂直分隔 | 表示不同角色 |
3.5 状态图 (State Diagram)
用途:描述单个对象在其生命周期内的状态变化
核心元素
| 元素 | 符号 | 说明 |
|---|---|---|
| 初始状态 | ● | 对象创建时的状态 |
| 终止状态 | ⊙ | 对象销毁时的状态 |
| 状态 | 圆角矩形 | 对象的某种状态 |
| 转换 | 箭头 | 状态之间的迁移 |
转换标记
格式:事件[条件]/动作
四、UML图对比总结
| UML图 | 主要用途 | 核心元素 |
|---|---|---|
| 用例图 | 描述系统功能需求 | 参与者、用例、关系 |
| 类图 | 描述系统静态结构 | 类、接口、关系 |
| 对象图 | 类图的实例快照 | 对象、链接 |
| 序列图 | 描述对象交互的时间顺序 | 生命线、消息、激活 |
| 活动图 | 描述业务流程 | 活动、控制流、泳道 |
| 状态图 | 描述对象状态变化 | 状态、转换、事件 |
| 构件图 | 描述系统物理模块 | 构件、接口、依赖 |
| 部署图 | 描述硬件软件部署 | 节点、制品、连接 |
五、考试要点
高频考点
- 用例图关系辨析:区分include和extend
- 类图关系识别:区分聚合和组合、泛化和实现
- 类图符号含义:+/-/#的含义,菱形方向
- 图类型选择:根据需求选择合适的UML图
典型例题
题1:在用例图中,基本用例"登录"必须执行"验证密码"用例,应该用什么关系? 答案:<<include>> 关系,因为是必须执行
题2:部门和员工的关系,应该用聚合还是组合? 答案:聚合(空心菱形),因为员工可以独立于部门存在
题3:类A的方法参数中使用了类B,这是什么关系? 答案:依赖关系
关系强度记忆
依赖 < 关联 < 聚合 < 组合 < 泛化/实现
虚线 → 实线
空心菱形 → 实心菱形