第 11 章:构建可复用的协议化框架
11.2 协议与模块化开发的结合
模块化开发是一种将复杂系统拆分为独立、可复用模块的设计方法,能够提高代码的可维护性和团队协作效率。Swift 的协议化编程(Protocol-Oriented Programming, POP)与模块化开发天然契合,通过定义清晰的接口和行为约束,可以实现模块之间的低耦合和高内聚。本节将探讨如何将协议与模块化开发结合,设计一个模块化的框架,并以一个“通知系统”为例展示具体实现。
模块化开发与协议的优势
在模块化开发中,协议提供了以下关键支持:
- 接口定义:协议作为模块之间的契约,确保模块间的通信清晰且类型安全。
- 依赖解耦:通过依赖注入和协议抽象,模块无需直接依赖具体实现。
- 可替换性:模块可以通过不同的协议实现替换,增强灵活性。
- 测试便利:协议便于 mock 实现,简化单元测试。
设计一个模块化的通知系统
我们将设计一个通知系统框架,包含以下模块:
- 核心模块:定义通知的发送和接收接口。
- 存储模块:管理通知数据的持久化。
- 展示模块:处理通知的 UI 显示。
1. 定义核心协议
核心模块通过协议定义通知系统的基本行为:
// 通知模型协议
protocol NotificationItem {
var id: String { get }
var title: String { get }
var message: String { get }
}
// 通知发送者协议
protocol NotificationSender {
func send(notification: NotificationItem)
}
// 通知接收者协议
protocol NotificationReceiver {
func receive(notification: NotificationItem)
}
// 通知管理器协议
protocol NotificationManaging {
func registerReceiver(_ receiver: NotificationReceiver)
func unregisterReceiver(_ receiver: NotificationReceiver)
func dispatch(notification: NotificationItem)
}
NotificationItem定义通知的基本结构。NotificationSender和NotificationReceiver分别抽象发送和接收行为。NotificationManaging协调通知的分发。
2. 实现核心模块
核心模块提供通知管理器的默认实现:
class NotificationManager: NotificationManaging {
private var receivers: [NotificationReceiver] = []
private let sender: NotificationSender
init(sender: NotificationSender) {
self.sender = sender
}
func registerReceiver(_ receiver: NotificationReceiver) {
receivers.append(receiver)
}
func unregisterReceiver(_ receiver: NotificationReceiver) {
receivers.removeAll { $0 === receiver }
}
func dispatch(notification: NotificationItem) {
sender.send(notification: notification)
receivers.forEach { $0.receive(notification: notification) }
}
}
NotificationManager依赖一个NotificationSender,并维护一组NotificationReceiver。dispatch方法将通知发送并分发给所有注册的接收者。
3. 实现存储模块
存储模块负责通知的持久化,使用协议解耦存储实现:
// 通知存储协议
protocol NotificationStorage {
func save(notification: NotificationItem)
func loadAll() -> [NotificationItem]
}
// UserDefaults 存储实现
struct UserDefaultsNotificationStorage: NotificationStorage {
private let defaults: UserDefaults
private let key = "notifications"
init(defaults: UserDefaults = .standard) {
self.defaults = defaults
}
func save(notification: NotificationItem) {
var notifications = loadAll()
notifications.append(notification)
let data = try? JSONEncoder().encode(notifications)
defaults.set(data, forKey: key)
}
func loadAll() -> [NotificationItem] {
guard let data = defaults.data(forKey: key),
let notifications = try? JSONDecoder().decode([CodableNotification].self, from: data) else {
return []
}
return notifications
}
}
// 辅助模型,确保可编码
struct CodableNotification: NotificationItem, Codable {
let id: String
let title: String
let message: String
}
NotificationStorage定义存储接口,UserDefaultsNotificationStorage是具体实现。- 存储模块独立于核心模块,仅通过协议交互。
4. 实现展示模块
展示模块处理通知的 UI 显示,使用协议抽象视图行为:
// 通知视图协议
protocol NotificationView: NotificationReceiver {
func showNotification(_ notification: NotificationItem)
}
// UIKit 视图控制器实现
class NotificationViewController: UIViewController, NotificationView {
private var notifications: [NotificationItem] = []
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
}
func receive(notification: NotificationItem) {
notifications.append(notification)
showNotification(notification)
}
func showNotification(_ notification: NotificationItem) {
let alert = UIAlertController(title: notification.title, message: notification.message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
}
NotificationView继承NotificationReceiver,并添加显示方法。NotificationViewController是 UIKit 中的具体实现,可以替换为 SwiftUI 或其他视图。
5. 模块组合与使用
将模块组合起来,形成完整的通知系统:
// 简单通知发送者实现
struct ConsoleNotificationSender: NotificationSender {
func send(notification: NotificationItem) {
print("Sending notification: \(notification.title) - \(notification.message)")
}
}
// 使用示例
let sender = ConsoleNotificationSender()
let manager = NotificationManager(sender: sender)
let storage = UserDefaultsNotificationStorage()
let viewController = NotificationViewController()
manager.registerReceiver(viewController)
manager.registerReceiver(storage)
let notification = CodableNotification(id: "1", title: "Update", message: "New version available!")
manager.dispatch(notification: notification)
// 检查存储
let savedNotifications = storage.loadAll()
print("Stored notifications: \(savedNotifications.count)")
- 核心模块(
NotificationManager)协调通知的分发。 - 存储模块(
UserDefaultsNotificationStorage)持久化通知。 - 展示模块(
NotificationViewController)显示通知。
模块化与协议的结合优势
- 独立性:每个模块(核心、存储、展示)独立开发和测试,仅通过协议交互。
- 可替换性:可以替换
NotificationSender(如用网络发送)、NotificationStorage(如用数据库)或NotificationView(如用 SwiftUI)。 - 扩展性:新增模块只需实现相应协议,无需修改现有代码。
- 低耦合:模块之间通过协议解耦,减少直接依赖。
小结
通过将协议化编程与模块化开发结合,我们构建了一个灵活的通知系统框架。协议定义了模块间的接口,模块化设计确保了职责分离和独立性。这种方法适用于任何需要复用的框架开发,下一节将通过一个日志系统的实战案例进一步展示其实用性。
