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

第2章:Swift 协议的基础

2.6 实战案例:用协议实现简单的模型层

在学习了协议的定义、属性要求、方法要求以及不同类型的实现方式后,本节将通过一个实战案例展示如何将这些知识应用到实际开发中。我们将设计一个简单的模型层,用于表示和管理应用程序中的数据实体。通过使用协议,我们将实现松耦合、可扩展的代码结构,并体现协议化编程(POP)的优势。

案例背景

假设我们要开发一个任务管理应用,需要表示“任务”(Task)实体。任务具有标题、优先级和完成状态,并且可以被持久化(例如保存到本地)。我们希望设计一个灵活的模型层,支持不同类型的任务,并便于后续扩展(如添加网络同步功能)。

设计协议

首先,我们定义核心协议来抽象任务的行为和属性:

// 表示任务的基本属性和行为
protocol Task {
    var title: String { get }
    var priority: Int { get set }
    var isCompleted: Bool { get set }
    func markAsCompleted()
}

// 表示可持久化的任务
protocol Persistable {
    func save() -> Bool
    func load() -> Bool
}
  • Task 协议定义了任务的基本要求:只读标题、可读写的优先级和完成状态,以及标记完成的方法。
  • Persistable 协议定义了持久化相关的行为,独立于任务逻辑,便于复用。

实现任务模型

接下来,我们用结构体实现一个具体的任务类型,遵循 Task 和 Persistable 协议:

struct SimpleTask: Task, Persistable {
    let title: String
    var priority: Int
    var isCompleted: Bool
    
    init(title: String, priority: Int = 0) {
        self.title = title
        self.priority = priority
        self.isCompleted = false
    }
    
    mutating func markAsCompleted() {
        isCompleted = true
        print("\(title) marked as completed")
    }
    
    func save() -> Bool {
        // 模拟保存到本地
        print("Saving \(title) with priority \(priority)")
        return true
    }
    
    func load() -> Bool {
        // 模拟从本地加载
        print("Loading \(title)")
        return true
    }
}
  • SimpleTask 是一个值类型的结构体,适合表示不可变标题和可变状态的任务。
  • markAsCompleted() 使用 mutating 关键字修改 isCompleted。
  • save() 和 load() 模拟持久化逻辑,返回布尔值表示操作成功与否。

测试模型层

让我们创建并使用这个任务模型:

var task = SimpleTask(title: "Write documentation", priority: 2)
print(task.title)        // 输出: Write documentation
print(task.isCompleted)  // 输出: false

task.markAsCompleted()   // 输出: Write documentation marked as completed
print(task.isCompleted)  // 输出: true

task.priority = 3
task.save()              // 输出: Saving Write documentation with priority 3
task.load()              // 输出: Loading Write documentation

这个简单的测试展示了任务的基本功能和持久化能力。

扩展模型层

假设我们需要支持一种带有描述的“详细任务”,可以通过协议继承和组合扩展现有模型:

protocol DetailedTask: Task {
    var description: String { get }
}

struct DetailedSimpleTask: DetailedTask, Persistable {
    let title: String
    var priority: Int
    var isCompleted: Bool
    let description: String
    
    init(title: String, description: String, priority: Int = 0) {
        self.title = title
        self.description = description
        self.priority = priority
        self.isCompleted = false
    }
    
    mutating func markAsCompleted() {
        isCompleted = true
        print("\(title) (Detailed) marked as completed")
    }
    
    func save() -> Bool {
        print("Saving \(title) with description: \(description)")
        return true
    }
    
    func load() -> Bool {
        print("Loading \(title) with description")
        return true
    }
}

var detailedTask = DetailedSimpleTask(
    title: "Review code",
    description: "Check for bugs and style",
    priority: 1
)
detailedTask.markAsCompleted() // 输出: Review code (Detailed) marked as completed
detailedTask.save()           // 输出: Saving Review code with description: Check for bugs and style
  • DetailedTask 继承 Task,添加了 description 属性要求。
  • DetailedSimpleTask 实现了 DetailedTask 和 Persistable,扩展了功能。

使用协议组合增强灵活性

我们可以用协议组合定义一个通用的操作函数,处理同时满足 Task 和 Persistable 的对象:

func processTask(_ task: Task & Persistable) {
    print("Processing \(task.title)")
    task.load()
    if !task.isCompleted {
        task.markAsCompleted()
    }
    task.save()
}

processTask(task)         // 处理 SimpleTask
processTask(detailedTask) // 处理 DetailedSimpleTask

输出:

Processing Write documentation
Loading Write documentation
Saving Write documentation with priority 3
Processing Review code
Loading Review code with description
Saving Review code with description: Check for bugs and style

案例分析:POP 的优势

  1. 松耦合:Task 和 Persistable 分离了任务逻辑和持久化逻辑,便于独立修改或复用。
  2. 可扩展性:通过继承(DetailedTask)和组合(Task & Persistable),轻松添加新功能。
  3. 值语义:使用结构体避免了引用共享,确保数据一致性。
  4. 类型安全:Swift 的类型系统保证了所有要求都被正确实现。

注意事项

  • 协议设计:保持协议单一职责,避免过于复杂的接口。
  • 实现选择:本案例使用结构体,但类或枚举也可根据需求使用(例如类适合共享状态)。
  • 测试覆盖:实际开发中应为每个方法添加单元测试,确保功能正确。

小结

通过这个实战案例,我们用协议实现了一个简单的模型层,展示了如何定义协议、实现具体类型以及扩展功能。协议化编程的核心在于抽象行为而非具体实现,这种方法为任务管理提供了灵活性和可维护性。下一章将介绍协议扩展,进一步提升代码复用性和设计能力。


Last Updated:: 3/9/25, 2:18 PM