一、协议爆炸的根源
-
每增加一个小功能就创建一个协议
- 结果:几十、上百个小协议 → 难以追踪
-
协议职责不清
- 一个协议承载多个能力 → 后续扩展难以组合
-
缺乏层次化 / 模块化
- 协议散落在全局 → 难以归类与复用
二、设计原则
-
单一职责原则(SRP)
- 一个协议只抽象一种能力
- 避免“巨型协议”承载多个行为
-
模块化 + 命名空间
- 协议按模块或功能域组织
- 命名清晰,例如:
Networking.Requestable、UI.Refreshable
-
组合优先而非继承
- 小协议组合 → 避免多继承或深层继承树
- 通过
typealias或协议组合形成复合能力
-
默认实现 / 模板方法复用
- 减少每个协议都需要 conforming 类型实现重复逻辑
-
协议分层
- 基础协议:核心能力
- 高阶协议:组合多个基础能力
- Extension 提供默认实现
三、工程实践策略
1️⃣ 协议分层设计
// 基础协议
protocol Flyable { func fly() }
protocol Swimmable { func swim() }
// 高阶协议组合
protocol SuperAnimal: Flyable, Swimmable {}
// 默认实现
extension Flyable { func fly() { print("Flying") } }
extension Swimmable { func swim() { print("Swimming") } }
- 小协议 → 单一能力
- 高阶协议 → 复合能力 → 避免重复创建新协议
2️⃣ 命名空间 + 模块化
enum Networking {
protocol Requestable { func request() }
}
enum UI {
protocol Refreshable { func refreshUI() }
}
- 避免协议全局污染
- 便于查找和维护
3️⃣ 使用 typealias 组合协议
protocol Drawable { func draw() }
protocol Animatable { func animate() }
typealias DrawableAnimatable = Drawable & Animatable
struct Sprite: DrawableAnimatable {
func draw() { print("Draw") }
func animate() { print("Animate") }
}
- 避免为每种组合创建新协议
- 保持协议数量可控
4️⃣ 默认实现 / 模板方法复用
protocol Logger { func log(message: String) }
extension Logger {
func log(message: String) { print("Log: (message)") }
}
struct FileLogger: Logger {}
struct ConsoleLogger: Logger {}
- 所有类型直接复用默认实现 → 避免每个类型都实现重复方法
- 减少“重复协议 + 方法”带来的膨胀
5️⃣ 工程管理策略
| 策略 | 说明 |
|---|---|
| 单一职责 | 一个协议只关注一种能力 |
| 模块化 / 命名空间 | 按功能域管理协议 |
| 小协议 + 高阶组合 | 避免重复创建协议 |
| 默认实现 / 模板方法 | 提供复用逻辑,减少 conforming 重复 |
| typealias 组合协议 | 减少组合协议数量 |
四、设计口诀
“小协议单一能力 → 高阶组合复用;
模块化管理命名 → 避免全局膨胀;
默认实现复用 → 减少重复;
typealias 组合 → 控制协议数量。”