第12章 面向对象程序设计
本章对应下午试卷中的“面向对象程序设计”选答题。它表面上叫程序设计,实际考法不是让你现场从零写一个系统,而是在给定类图、题干说明和 Java/C++ 代码框架的基础上做代码填空。满分通常为 15 分,目标不是把所有空都啃下来,而是稳定拿到语法空、角色空、调用关系空,争取 6-9 分以上。
本章学习地图
| 小节 | 题型核心 | 主要能力 | 最容易丢分的地方 |
|---|---|---|---|
| 访问者模式 | 对象结构稳定,操作变化 | 读懂 accept(visitor) 与 visit(element) 的双分派 | this 参数、接口方法签名、抽象方法漏写 |
| 生成器模式 | 分步骤构造复杂对象 | 区分 Builder、ConcreteBuilder、Director、Product | abstract、this.xxx = xxx、Director 调用顺序 |
| 适配器模式 | 接口不兼容时做转换 | 建立原接口与目标接口的对应关系 | 成员变量类型、构造函数赋值、父类引用指向子类对象 |
| 桥接模式 | 两个维度独立变化 | 拆分抽象维度与实现维度,避免类爆炸 | 接口方法声明、表格方法名、参数顺序 |
这类题真正考什么
面向对象程序设计题通常是 Java 与 C++ 二选一。考试答题卡只有一个作答区域,必须涂选你选择的题号;如果不涂,阅卷可能按默认题目规则处理,选了另一种语言也可能无法得分。
这类题的分值来源可以拆成三层:
| 层次 | 考查内容 | 得分策略 |
|---|---|---|
| 语法层 | 类、接口、抽象方法、构造函数、成员变量、对象实例化 | 先拿稳,不依赖完整理解设计模式 |
| 结构层 | 抽象类与子类、接口与实现类、父类引用与子类对象 | 用上下文“抄结构”,尤其是方法签名 |
| 模式层 | 访问者、生成器、适配器、桥接的角色协作 | 用模式意图判断调用方向和对象关系 |
Java 与 C++ 常考语法坑
| 考点 | Java 写法 | C++ 写法 | 做题提醒 |
|---|---|---|---|
| 类定义 | class A { ... } | class A { ... }; | C++ 类定义末尾有分号 |
| 接口/抽象 | interface I、abstract class A | 纯虚函数模拟接口 | Java 接口方法没有方法体;抽象类中的抽象方法要写 abstract |
| 纯虚函数 | 不使用 = 0 | virtual void f() = 0; | C++ 填空别漏 virtual、参数列表和 = 0 |
| 继承/实现 | extends、implements | class B : public A | Java 单继承多实现;C++ 可多重继承 |
| 成员访问 | obj.method() | 对象用 .,指针用 -> | C++ 中 * 定义指针,指针访问成员用箭头 |
| 类外定义 | 不常见 | ReturnType ClassName::method(...) | :: 前面是类名,不是方法名 |
| 当前对象 | this.field | this->field 或直接写成员 | 参数名与成员名相同时,必须用 this 区分 |
读代码填空的顺序
mermaid
flowchart TD
A["先读题干:业务对象和变化点"] --> B["看类图:类名、继承、接口、组合关系"]
B --> C["扫代码空所在位置:类声明/成员变量/构造函数/方法体/主函数"]
C --> D{"空属于哪类?"}
D --> E["声明空:从子类实现或接口约束反推方法签名"]
D --> F["赋值空:看构造函数参数与成员变量"]
D --> G["调用空:看当前可用对象能调用哪些方法"]
D --> H["实例化空:类名 对象名 = new 子类名(参数)"]
E --> I["再用设计模式校验调用方向"]
F --> I
G --> I
H --> I四种模式的代码直觉
| 模式 | 一句话判断 | 代码里的典型形状 |
|---|---|---|
| 访问者 | “我不改元素类,只新增访问操作” | 元素 accept(v) 内部调用 v.visit(this) |
| 生成器 | “步骤相同,产品内容不同” | Director/服务员持有 Builder,并按步骤调用 create、build、get |
| 适配器 | “已有接口不能直接用,需要翻译” | Adapter 持有 Adaptee,目标方法内部调用已有对象的方法 |
| 桥接 | “两个维度都要扩展,继承会爆炸” | 抽象类持有实现接口,业务方法委托给实现对象 |
本章复习标准
学完本章,不要求把每道题所有代码背下来,而要能做到:
- 看到
abstract class能判断是否缺抽象方法。 - 看到
interface能从实现类反推接口方法声明。 - 看到构造函数能判断成员变量、参数、
this的关系。 - 看到方法体空缺能先列出当前对象、参数对象、成员对象各自可调用的方法。
- 看到主函数实例化能写出“父类/接口类型引用 = new 具体子类(已有参数)”。
- 看到表格或特殊说明能意识到它不是装饰信息,后面的代码填空通常会用到。