目录 · ← l29
3.16 设计模式速查(全课程出现的模式)
| 模式 | 用途 | 出现在 |
|---|
| ADT / 封装 | 分离使用与实现 | R10–R12 |
| 迭代器 Iterator | 顺序访问而不暴露内部表示 | R8、R12 |
| 工厂方法 Factory | 把创建逻辑与使用解耦(creator) | R10 |
| 观察者 / 监听器 Listener | 事件源通知多个订阅者 | R20 |
| 回调 Callback | 把控制流的”下一步”作为参数传入 | R16、R20 |
| 不可变对象 Immutable | 免于别名 bug、天然线程安全 | R8、R21 |
| 组合模式 Composite | 用统一接口处理”单个”与”组合” | R26 |
| 解释器 Interpreter | 递归数据类型 + 求值函数 = 小语言 | R26 |
| 访问者 Visitor | 不改数据类型就增加新操作 | R27 |
| 监视器 Monitor | 用锁把 ADT 变成线程安全的 | R23 |
| 生产者-消费者 | 用阻塞队列解耦生产与消费速度 | R24 |
| 客户端/服务器 | 通过网络通信的两个角色 | R25 |
3.17 一页纸复习:20 条黄金法则
- 先写规格,再写实现。 说不清”做什么”就不该开始写”怎么做”。
- 前置条件是调用者的义务,后置条件是实现者的义务。 不要搞反。
- 规格要声明式,不要操作式。
- 允许实现自由度:除非调用者真的依赖,否则不要规定唯一答案。
- 把
null 赶出你的接口。 - 优先不可变;可变对象必须小心别名。
- 可变对象进出 ADT 都要防御性拷贝。
final 只防重新赋值,不防内部可变。- AF 和 RI 必须写成代码注释,否则它们不存在。
- 所有构造函数建立 RI,所有 mutator 保持 RI,所有 observer 假设 RI 成立。
checkRep() 放在每个构造函数和 mutator 的末尾。equals 相等 ⟹ hashCode 相等;hashCode 绝不能用可变字段。- 可变类型用引用相等,不可变类型用值相等。
- 测试先写,测试要能失败,边界值优先。
- fail fast:错误越早暴露越便宜。
- DRY:重复的代码是未来 bug 的温床。
- 避免共享可变状态;做不到就用锁或消息传递保护它。
- 统一锁顺序以避免死锁。
- 并发正确性靠设计保证,不能靠测试碰运气。
- 代码是写给人读的——包括未来的你。