ARTICLE · 1133933
冲刺Day 3 - 软件工程
🎯 今日冲刺目标
分清六大开发模型的适用场景(必考选择题)
掌握需求分类:功能需求 vs 非功能需求 vs 设计约束(必考)
记住 23 个 GoF 设计模式的分类与意图(必考,年年出)
理解软件测试四层金字塔与 McCabe 复杂度计算(高频)
能判断 UML 七种图的用途(高频)
📅 建议用时:90 分钟📊 目标分值:综合知识 8~12 分
📋 核心考点速查
一、软件开发模型 🔴★★★★★
| 模型 | 核心特点 | 适用场景 | 缺点 |
|---|---|---|---|
| 瀑布模型 | 线性顺序,阶段间有明确文档 | 需求明确、变更少 | 不适应需求变化,后期才发现错误 |
| 增量模型 | 分批次交付,每次增加一部分功能 | 需求大体明确,可分批交付 | 需要开放式架构 |
| 演化(原型)模型 | 快速构建原型,逐步细化 | 需求不明确,需要用户反馈 | 原型可能被误当最终产品 |
| 螺旋模型 | 每轮迭代包含风险分析 | 大型、高风险项目 | 成本高,需要风险评估能力 |
| V 模型 | 测试与开发阶段一一对应 | 强调测试的项目 | 测试仍在编码之后 |
| 敏捷开发 | 迭代增量、拥抱变化、小步快跑 | 需求变化频繁,小团队 | 文档不足,依赖团队能力 |
「口诀」:需求清楚用瀑布,风险大用螺旋,需求不清用原型,分批交付用增量
敏捷四大价值观(《敏捷宣言》):
个体和交互 胜过 过程和工具
工作的软件 胜过 详尽的文档
客户合作 胜过 合同谈判
响应变化 胜过 遵循计划
二、需求工程 🔴★★★★
2.1 需求分类
| 类型 | 说明 | 举例 |
|---|---|---|
| 功能需求 | 系统做什么 | "用户能通过手机号登录" |
| 非功能需求 | 系统做得怎么样 | "响应时间不超过 2 秒" |
| 设计约束 | 技术选型限制 | "必须使用 MySQL 数据库" |
2.2 需求获取方法
| 方法 | 适用场景 |
|---|---|
| 用户访谈 | 获取深层需求,了解用户真实想法 |
| 问卷调查 | 大范围收集需求 |
| 观察( ethnography) | 用户无法清楚表达的工作流程 |
| 原型法 | 需求不明确,需要可视化确认 |
| 文档分析 | 从现有系统文档中提取需求 |
2.3 需求管理
需求获取 → 需求分析 → 需求规格说明 → 需求验证 → 需求变更管理⚠️ 需求变更:必须有变更控制流程(提出→评估→审批→实施→验证),不能随意变更。
三、设计原则(SOLID) 🔴★★★★
| 原则 | 缩写 | 含义 | 记忆关键词 |
|---|---|---|---|
| 单一职责 | SRP | 一个类只做一件事 | 一个原因导致变化 |
| 开闭 | OCP | 对扩展开放,对修改关闭 | 加新功能不改旧代码 |
| 里氏替换 | LSP | 子类能替换父类不出错 | 子类是父类的特例 |
| 接口隔离 | ISP | 客户端不依赖它不用的接口 | 接口要小而专 |
| 依赖倒置 | DIP | 依赖抽象,不依赖具体 | 面向接口编程 |
「口诀」:S 单一,O 开闭,L 里氏,I 隔离,D 倒置
四、23 个 GoF 设计模式 🔴★★★★★
4.1 创建型模式(5 个)—— "怎么创建对象"
| 模式 | 意图 | 典型应用 |
|---|---|---|
| 单例 | 保证一个类只有一个实例 | 配置管理器、连接池 |
| 工厂方法 | 定义创建对象的接口,子类决定创建哪个 | 日志框架(不同日志实现) |
| 抽象工厂 | 创建一系列相关对象 | 跨平台 UI 组件(按钮+文本框+菜单) |
| 建造者 | 分步构建复杂对象 | StringBuilder、构造复杂配置 |
| 原型 | 通过克隆已有对象创建新对象 | 对象深拷贝 |
4.2 结构型模式(7 个)—— "怎么组合类和对象"
| 模式 | 意图 | 典型应用 |
|---|---|---|
| 适配器 | 将不兼容接口转换为可用接口 | 电源转换插头、旧系统接口适配 |
| 桥接 | 将抽象与实现分离,使两者独立变化 | 跨平台图形接口 |
| 组合 | 将对象组合成树形结构表示"部分-整体" | 文件系统、菜单嵌套 |
| 装饰 | 动态地给对象添加额外功能 | Java I/O 流(BufferedReader 包装 FileReader) |
| 外观 | 为子系统提供统一的高层接口 | 一键启动(封装多个子系统调用) |
| 享元 | 共享细粒度对象以减少数量 | 字符串常量池、棋盘棋子 |
| 代理 | 为其他对象提供替身以控制访问 | 远程代理、延迟加载 |
4.3 行为型模式(11 个)—— "对象之间怎么交互"
| 模式 | 意图 | 典型应用 |
|---|---|---|
| 观察者 | 一对多依赖,状态变化通知所有观察者 | 事件监听、消息订阅 |
| 策略 | 定义一系列算法,使它们可以互换 | 排序策略(冒泡/快排/归并) |
| 模板方法 | 定义算法骨架,子类填充细节 | 框架的 init→process→destroy |
| 命令 | 将请求封装为对象 | 撤销/重做功能 |
| 迭代器 | 顺序访问集合元素而不暴露内部结构 | for-each 循环底层 |
| 责任链 | 请求沿链传递,直到有对象处理它 | 过滤器链、审批流程 |
| 状态 | 对象行为随内部状态改变 | 订单状态机(待付款→已付款→已发货) |
| 中介者 | 用中介对象封装多个对象的交互 | 聊天室(所有消息经服务器转发) |
| 备忘录 | 保存和恢复对象状态 | 编辑器撤销 |
| 访问者 | 在不修改类的前提下增加新操作 | 编译器对 AST 做类型检查、代码生成 |
| 解释器 | 定义文法并构建解释器 | 正则表达式引擎、SQL 解析 |
「口诀」:创建 5 个管创建,结构 7 个管组合,行为 11 个管交互
五、软件测试 🟡★★★★
5.1 测试层次金字塔
/ 验收测试 \ ← 用户参与,验证业务需求 / 系统测试 \ ← 验证整体功能和非功能需求 / 集成测试 \ ← 验证模块间接口 / 单元测试 \ ← 验证单个模块/函数
5.2 黑盒 vs 白盒
| 对比 | 黑盒测试 | 白盒测试 |
|---|---|---|
| 关注点 | 功能是否正确 | 内部逻辑是否正确 |
| 是否看代码 | 不看 | 看 |
| 典型方法 | 等价类划分、边界值、因果图 | 语句覆盖、分支覆盖、路径覆盖 |
| 执行者 | 测试人员 | 开发人员 |
5.3 白盒覆盖级别(从弱到强)
语句覆盖 → 判定覆盖(分支覆盖)→ 条件覆盖 → 判定/条件覆盖 → 条件组合覆盖 → 路径覆盖5.4 McCabe 环路复杂度
V(G) = E - N + 2E = 边数,N = 节点数
或:V(G) = 判定节点数 + 1
六、UML 图 🟡★★★★
| 图名 | 用途 | 分类 |
|---|---|---|
| 用例图 | 描述系统功能和使用者关系 | 需求阶段 |
| 类图 | 描述类及其关系(关联、继承、依赖) | 静态结构 |
| 对象图 | 类图的实例,某时刻的快照 | 静态结构 |
| 序列图(顺序图) | 对象间消息的时间顺序 | 动态行为 |
| 活动图 | 类似流程图,描述工作流 | 动态行为 |
| 状态图 | 对象的状态转换 | 动态行为 |
| 组件图 | 系统的物理组件结构 | 实现 |
「口诀」:用例看功能,类图看结构,序列看时序,活动看流程,状态看转换
✍️ 原创冲刺精练(10 题)
【第 1 题】 某项目需求不明确,用户无法清楚描述所需功能,且项目存在较高技术风险。最适合采用的开发模型是( )。
A. 瀑布模型
B. 螺旋模型
C. V 模型
D. 增量模型
【第 2 题】 "系统应支持 1000 个用户同时在线,响应时间不超过 3 秒"属于( )需求。
A. 功能需求
B. 非功能需求
C. 设计约束
D. 业务规则
【第 3 题】 在设计模式中,"将一个类的接口转换成客户希望的另一个接口"描述的是( )模式。
A. 代理
B. 装饰
C. 适配器
D. 桥接
【第 4 题】 某程序的控制流图有 8 个节点、10 条边,则 McCabe 环路复杂度为( )。
A. 2
B. 4
C. 6
D. 8
【第 5 题】 下列关于设计模式分类的说法中,正确的是( )。
A. 单例模式属于结构型模式
B. 观察者模式属于行为型模式
C. 适配器模式属于创建型模式
D. 策略模式属于结构型模式
【第 6 题】 在 UML 中,用于描述对象之间消息传递时间顺序的图是( )。
A. 用例图
B. 类图
C. 序列图
D. 活动图
【第 7 题】 在面向对象设计中,"开放-封闭原则"(OCP)的含义是( )。
A. 一个类应该只有一个引起变化的原因
B. 软件实体应对扩展开放,对修改关闭
C. 子类应该能替换其父类
D. 要依赖抽象,不要依赖具体类
【第 8 题】 某电商系统的订单有"待付款""已付款""已发货""已完成""已取消"五种状态,不同状态下的操作不同。最适合使用( )设计模式来管理状态转换。
A. 策略
B. 状态
C. 模板方法
D. 观察者
【第 9 题】 下列测试方法中,属于白盒测试的是( )。
A. 等价类划分
B. 边界值分析
C. 路径覆盖
D. 因果图
【第 10 题】 下列关于敏捷开发的描述中,不符合《敏捷宣言》价值观的是( )。
A. 重视团队成员之间的面对面沟通
B. 工作的软件是进度的主要度量
C. 必须严格遵循项目初期制定的计划
D. 欢迎需求变化,即使在开发后期
📖 答案与详解
第 1 题 答案:B
考点:开发模型选择
详解:
题目关键词:需求不明确 + 技术风险高
螺旋模型 = 原型模型 + 风险分析,特别适合高风险大型项目
原型模型也适合需求不明确,但没有强调风险分析
瀑布模型适合需求明确的项目
V 模型强调测试
增量模型适合需求大体明确、可分批交付
第 2 题 答案:B
考点:需求分类
详解:
"1000 个用户同时在线"→ 性能指标
"响应时间不超过 3 秒"→ 性能指标
这些描述的是系统"做得怎么样",不是"做什么"→ 非功能需求
功能需求描述具体功能(如"用户可以下单")
设计约束是技术选型限制(如"必须用 Java")
第 3 题 答案:C
考点:设计模式意图识别
详解:
"将一个接口转换成另一个接口"= 适配器的经典定义
适配器 = 转换插头,让不兼容的接口能协作
代理 = 控制对对象的访问
装饰 = 动态添加功能
桥接 = 将抽象与实现分离
第 4 题 答案:B
考点:McCabe 环路复杂度
详解:
V(G) = E - N + 2 = 10 - 8 + 2 = 4
也可以用:V(G) = 判定节点数 + 1
环路复杂度 = 独立路径的数量 = 测试需要覆盖的最少路径数
第 5 题 答案:B
考点:设计模式分类
详解:
A 错误:单例属于创建型模式
B 正确:观察者属于行为型模式 ✓
C 错误:适配器属于结构型模式
D 错误:策略属于行为型模式
第 6 题 答案:C
考点:UML 图类型
详解:
序列图(顺序图):按时间顺序显示对象间的消息交互
用例图:系统功能与参与者关系
类图:类的静态结构
活动图:工作流程(类似流程图)
第 7 题 答案:B
考点:SOLID 原则
详解:
A 是单一职责原则(SRP)
B 是开放-封闭原则(OCP)✓
C 是里氏替换原则(LSP)
D 是依赖倒置原则(DIP)
第 8 题 答案:B
考点:设计模式应用场景
详解:
题目描述:对象有不同状态,不同状态下行为不同
状态模式:将状态封装为类,行为随状态改变
策略:虽然也是切换算法,但侧重于外部选择策略,不是自动根据内部状态切换
模板方法:定义骨架,子类填充
观察者:一对多通知
第 9 题 答案:C
考点:白盒测试方法
详解:
白盒测试需要看代码结构:语句覆盖、分支覆盖、路径覆盖等
黑盒测试不看代码:等价类划分、边界值分析、因果图
路径覆盖属于白盒测试 ✓
第 10 题 答案:C
考点:敏捷宣言价值观
详解:
敏捷宣言明确说"响应变化胜过遵循计划"
C 说"必须严格遵循项目初期制定的计划"与敏捷价值观矛盾
A 符合"个体和交互胜过过程和工具"
B 符合"工作的软件胜过详尽的文档"
D 符合"响应变化胜过遵循计划"
⚠️ 易错陷阱 Top 5
| # | 陷阱 | 正确做法 |
|---|---|---|
| 1 | 螺旋模型和原型模型搞混 | 螺旋 = 原型 + 风险分析,关键词"风险"选螺旋 |
| 2 | 设计模式分类记混 | 创建 5(单例工厂等)、结构 7(适配桥接等)、行为 11(观察策略等) |
| 3 | McCabe 复杂度公式记错 | V(G) = E - N + 2,不是 E + N + 2 |
| 4 | 非功能需求和设计约束混淆 | 性能/安全/可用性 = 非功能需求;"必须用某技术" = 设计约束 |
| 5 | 装饰模式和适配器模式混淆 | 装饰 = 加功能(不改变接口);适配器 = 改接口(不加功能) |