iOS中的设计模式(十二)- 迭代器模式(Iterator Pattern)在 iOS 开发中的实践

一. 引言

很多开发者第一次接触迭代器模式时都会有一个疑问:为什么在实际开发中几乎没有写过迭代器?

但其实,在日常 iOS 开发中,我们几乎每天都会遍历数组、字典或者集合。例如:

Swift 复制代码
for item in array {
    print(item)
}

或者:

Swift 复制代码
array.forEach { item in
    print(item)
}

这些写法已经非常自然,以至于我们很少会思考:这些遍历背后的实现机制是什么?

事实上,这正是经典设计模式中的 迭代器模式(Iterator Pattern)

不过在现代 Swift 开发中,我们很少需要自己实现迭代器,因为 Swift 标准库已经把这一模式内置到了语言层面。但理解它依然很有价值,因为很多系统 API 和高级集合操作都是基于这一模式实现的。

本文我们就来一起看看 什么是迭代器模式,以及它在 iOS 开发中的实际应用方式。

二. 什么是迭代器

迭代器模式的核心思想是:在不暴露集合内部结构的情况下,顺序访问集合中的元素。

换句话说:

  • 集合负责存储数据
  • 迭代器负责遍历数据

调用者只需要关心下一个元素是谁。而不需要关心集合内部到底是数组、链表还是树。

这就实现了 访问逻辑与数据结构的解耦。

三. 传统迭代器模式

在经典设计模式中,迭代器通常包含以下几个角色:

Iterator(迭代器接口)

负责定义遍历方法,例如:

Swift 复制代码
next()
hasNext()

ConcreteIterator(具体迭代器)

真正实现遍历逻辑。

Aggregate(集合接口)

定义创建迭代器的方法。

ConcreteAggregate(具体集合)

具体的数据存储结构。

Swift 复制代码
Aggregate
   │
   └── createIterator()

Iterator
   ├── next()
   └── hasNext()

调用者通过迭代器来访问集合,而不是直接访问集合内部数据。

四. Swift 中的迭代器

在 Swift 中,这一模式已经被标准库封装为两个核心协议:

Swift 复制代码
Sequence
IteratorProtocol

IteratorProtocol

定义了最核心的方法:

Swift 复制代码
protocol IteratorProtocol {
    associatedtype Element
    mutating func next() -> Element?
}

next() 每次返回一个元素,当没有元素时返回 nil。

Sequence

Sequence 表示 一个可被遍历的集合。

Swift 复制代码
protocol Sequence {
    associatedtype Iterator: IteratorProtocol
    func makeIterator() -> Iterator
}

当一个类型遵守 Sequence 时,就可以被 for-in 遍历。

例如:

Swift 复制代码
let array = [1,2,3]

var iterator = array.makeIterator()

while let value = iterator.next() {
    print(value)
}

而我们平时写的:

Swift 复制代码
for value in array {
    print(value)
}

五. 实现一个自定义迭代器

接下来我们实现一个简单的例子:一副扑克牌 Deck。

目标是让它支持这样的遍历方式:

Swift 复制代码
for card in deck {
    print(card)
}

5.1 定义 Card 和 Deck

Swift 复制代码
struct Card {
    let suit: String
    let number: Int
}

class CardDeck {
    
    private var cards: [Card] = []
    
    init() {
        let suits = ["♠️","♥️","♣️","♦️"]
        
        for suit in suits {
            for number in 1...13 {
                cards.append(Card(suit: suit, number: number))
            }
        }
    }
}

这里我们创建了一副标准的 52 张牌。

5.2 创建 DeckIterator

Swift 复制代码
struct CardDeckIterator: IteratorProtocol {
    
    private var cards: [Card]
    private var index = 0
    
    init(cards: [Card]) {
        self.cards = cards
    }
    
    mutating func next() -> Card? {
        
        guard index < cards.count else {
            return nil
        }
        
        let card = cards[index]
        index += 1
        
        return card
    }
}

这个迭代器负责:

  1. 记录当前位置 index
  2. 每次返回一张牌
  3. 遍历结束返回 nil

5.3 让 Deck 支持遍历

接下来让 CardDeck 遵守 Sequence:

Swift 复制代码
extension CardDeck: Sequence {
    
    func makeIterator() -> CardDeckIterator {
        return CardDeckIterator(cards: cards)
    }
}

现在就可以这样使用了:

Swift 复制代码
let deck = CardDeck()

for card in deck {
    print(card)
}

六. 关于自己实现迭代器

但其实在客户端开发中,我们确实很少自己来写迭代器。主要是Swift的标准库就已经实现了,我们常用的集合类型:

Swift 复制代码
Array
Set
Dictionary

全部已经遵守 Sequence,因此我们天然就拥有了遍历能力。

除了我们常用的遍历函数,Swift还提供了很多基于迭代器的高级函数:

Swift 复制代码
map
filter
reduce
compactMap
forEach

我们使用起来又方便,又快捷。

另外就是通常在在客户端需要处理的业务数据结构都很简单,大多数APP中,我们就只需要使用 Array或者Dictionary就够了。很少会自己来实现复杂的集合结构,因此也就很少需要手写迭代器。

七. 结语

迭代器模式是一个非常经典的设计模式,它解决的问题其实非常简单:如何在不暴露内部结构的情况下遍历集合。

在现代 Swift 开发中,我们很少需要自己实现迭代器,因为Sequence,IteratorProtocol 已经把这一模式内置到了语言层面。

但理解它依然非常重要。

相关推荐
大数据新鸟14 小时前
设计模式详解——观察者模式
观察者模式·设计模式
武藤一雄16 小时前
C# 设计模式大全(第一弹|7种)
microsoft·设计模式·微软·c#·.net·.netcore
Aloha_up18 小时前
常见设计模式简介
设计模式
砍光二叉树20 小时前
【设计模式】行为型-迭代器模式
设计模式·迭代器模式
Elaine33620 小时前
【Agent 设计模式全景图:从 ReAct 到工业级多智能体架构】
设计模式·llm·软件架构·ai agent
han_21 小时前
JavaScript设计模式(六):职责链模式实现与应用
前端·javascript·设计模式
无籽西瓜a1 天前
【西瓜带你学设计模式 | 第三期-工厂方法模式】工厂方法模式——定义、实现方式、优缺点与适用场景以及注意事项
java·后端·设计模式·工厂方法模式
无籽西瓜a1 天前
【西瓜带你学设计模式 | 第四期 - 抽象工厂模式】抽象工厂模式 —— 定义、核心结构、实战示例、优缺点与适用场景及模式区别
java·后端·设计模式·软件工程·抽象工厂模式
￰meteor1 天前
23种设计模式 -【抽象工厂】
后端·设计模式
程序员小寒1 天前
JavaScript设计模式(五):装饰者模式实现与应用
前端·javascript·设计模式