Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain

第6章:协议在模块化架构中的应用

6.4 实战案例:构建一个模块化的任务管理系统

在前几节中,我们探讨了模块化架构的核心概念、使用协议定义模块接口以及模块间的通信机制。本节将通过一个实战案例,将这些知识整合应用,设计并实现一个模块化的任务管理系统。该系统将展示如何利用协议化编程(POP)实现模块解耦、通信和测试,体现模块化设计的实际价值。

案例背景

我们要开发一个任务管理系统,支持以下功能:

  • 添加和管理任务。
  • 记录任务日志。
  • 通知用户任务状态更新。
  • 支持不同存储方式(如内存、文件)。

目标是设计一个模块化系统,确保各模块独立、可替换,并易于测试。

系统模块划分

  1. 任务管理模块:负责任务的创建和状态管理。
  2. 存储模块:处理任务数据的持久化。
  3. 日志模块:记录任务操作日志。
  4. 通知模块:发送任务状态通知。
  5. 协调模块:整合各模块,协调业务逻辑。

第一步:定义模块接口

使用协议定义各模块的接口:

// 任务管理模块接口
protocol TaskManager {
    func addTask(title: String)
    func completeTask(id: String)
}

// 存储模块接口
protocol TaskStore {
    func saveTask(id: String, title: String, completed: Bool)
    func loadTasks() -> [Task]
    func updateTask(id: String, completed: Bool)
}

struct Task {
    let id: String
    let title: String
    var completed: Bool
}

// 日志模块接口
protocol Logger {
    func log(_ message: String)
}

// 通知模块接口
protocol Notifier {
    func notify(event: String, data: [String: Any])
}
  • 每个协议定义了模块的核心职责,保持单一性。

第二步:实现模块

为每个模块提供默认实现:

class InMemoryTaskStore: TaskStore {
    private var tasks: [String: Task] = [:]
    
    func saveTask(id: String, title: String, completed: Bool) {
        tasks[id] = Task(id: id, title: title, completed: completed)
    }
    
    func loadTasks() -> [Task] {
        return Array(tasks.values)
    }
    
    func updateTask(id: String, completed: Bool) {
        if var task = tasks[id] {
            task.completed = completed
            tasks[id] = task
        }
    }
}

struct ConsoleLogger: Logger {
    func log(_ message: String) {
        print("[Console] \(message)")
    }
}

struct PrintNotifier: Notifier {
    func notify(event: String, data: [String: Any]) {
        print("Notification: \(event) - \(data)")
    }
}

class TaskManagerImpl: TaskManager {
    private let store: TaskStore
    private let logger: Logger
    private let notifier: Notifier
    
    init(store: TaskStore, logger: Logger, notifier: Notifier) {
        self.store = store
        self.logger = logger
        self.notifier = notifier
    }
    
    func addTask(title: String) {
        let id = UUID().uuidString
        store.saveTask(id: id, title: title, completed: false)
        logger.log("Added task: \(title) (ID: \(id))")
        notifier.notify(event: "taskAdded", data: ["id": id, "title": title])
    }
    
    func completeTask(id: String) {
        store.updateTask(id: id, completed: true)
        logger.log("Completed task ID: \(id)")
        notifier.notify(event: "taskCompleted", data: ["id": id])
    }
}
  • TaskManagerImpl 依赖注入所有模块,协调任务操作。

第三步:协调模块

创建一个协调器整合系统:

class TaskSystemCoordinator {
    private let taskManager: TaskManager
    
    init(taskManager: TaskManager) {
        self.taskManager = taskManager
    }
    
    func start() {
        taskManager.addTask(title: "Write report")
        taskManager.addTask(title: "Review code")
        taskManager.completeTask(id: loadFirstTaskId())
    }
    
    private func loadFirstTaskId() -> String {
        // 假设从存储中获取第一个任务 ID
        return "some-id" // 简化处理,实际应从 store 获取
    }
}

let store = InMemoryTaskStore()
let logger = ConsoleLogger()
let notifier = PrintNotifier()
let taskManager = TaskManagerImpl(store: store, logger: logger, notifier: notifier)
let system = TaskSystemCoordinator(taskManager: taskManager)
system.start()
// 输出示例:
// [Console] Added task: Write report (ID: uuid1)
// Notification: taskAdded - ["id": "uuid1", "title": "Write report"]
// [Console] Added task: Review code (ID: uuid2)
// Notification: taskAdded - ["id": "uuid2", "title": "Review code"]
// [Console] Completed task ID: some-id
// Notification: taskCompleted - ["id": "some-id"]
  • TaskSystemCoordinator 通过注入 TaskManager 启动系统。

第四步:扩展模块

添加文件存储支持:

struct FileTaskStore: TaskStore {
    func saveTask(id: String, title: String, completed: Bool) {
        print("Saved to file: \(id) - \(title)")
    }
    
    func loadTasks() -> [Task] {
        return [Task(id: "file1", title: "File task", completed: false)]
    }
    
    func updateTask(id: String, completed: Bool) {
        print("Updated task \(id) in file to completed: \(completed)")
    }
}

let fileSystem = TaskSystemCoordinator(
    taskManager: TaskManagerImpl(store: FileTaskStore(), logger: logger, notifier: notifier)
)
fileSystem.start()
// 输出示例:
// Saved to file: uuid3 - Write report
// Notification: taskAdded - ["id": "uuid3", "title": "Write report"]
  • 无需修改核心逻辑即可切换存储模块。

第五步:测试模块

为 TaskManager 添加单元测试:

struct MockTaskStore: TaskStore {
    var tasks: [String: Task] = [:]
    func saveTask(id: String, title: String, completed: Bool) { tasks[id] = Task(id: id, title: title, completed: completed) }
    func loadTasks() -> [Task] { Array(tasks.values) }
    func updateTask(id: String, completed: Bool) { tasks[id]?.completed = completed }
}

struct MockLogger: Logger {
    var logs: [String] = []
    func log(_ message: String) { logs.append(message) }
}

struct MockNotifier: Notifier {
    var notifications: [(String, [String: Any])] = []
    func notify(event: String, data: [String: Any]) { notifications.append((event, data)) }
}

import XCTest
class TaskManagerTests: XCTestCase {
    func testAddTask() {
        let store = MockTaskStore()
        let logger = MockLogger()
        let notifier = MockNotifier()
        let manager = TaskManagerImpl(store: store, logger: logger, notifier: notifier)
        
        manager.addTask(title: "Test task")
        let taskId = store.tasks.keys.first!
        XCTAssertEqual(store.tasks[taskId]?.title, "Test task")
        XCTAssertEqual(logger.logs, ["Added task: Test task (ID: \(taskId))"])
        XCTAssertEqual(notifier.notifications[0].0, "taskAdded")
        XCTAssertEqual(notifier.notifications[0].1["title"] as? String, "Test task")
    }
}
  • Mock 对象验证了任务添加逻辑和通信行为。

案例分析

  1. 模块解耦:各模块通过协议交互,独立实现。
  2. 通信机制:使用依赖注入和通知模式,确保灵活性。
  3. 可测试性:Mock 实现隔离模块,便于单元测试。
  4. 扩展性:新存储或通知方式只需遵循协议即可。

注意事项

  • ID 处理:实际应用中需完善 ID 生成和获取逻辑。
  • 异步支持:可为存储或通知添加异步接口。
  • 依赖管理:大型系统可使用 DI 容器简化注入。

小结

通过构建一个模块化的任务管理系统,我们展示了协议在定义接口、实现通信和支持测试中的作用。这一案例体现了模块化架构的完整流程,为开发者提供了可复用的设计模板。下一章将探讨协议在跨平台开发中的应用,进一步扩展其潜力。


Last Updated:: 3/11/25, 11:48 AM