【设计模式】12 - 迭代器模式 (Iterator Pattern)

这篇文章是我阅读raywenderlich.com的Design Patterns by Tutorials的总结,文中的代码是我阅读书本之后根据自己的想法修改的。如果想看原版书籍,请点击链接购买。


迭代器模式提供了一种遍历集合的方式。这个模式设计两种类型:1) 迭代器协议;2) 自定义的可遍历的类型

Swift里面的集合可以通过for-in来遍历的类型,就是利用了迭代器协议IteratorProtocol

什么时候使用

当我们的class或者struct拥有一组排好序的对象,并且我们想通过for-in来遍历这组对象时,使用迭代器模式。

简单demo

我们实现一个队列,然后通过遵循Sequence协议,实现使用for-in来遍历队列里面的元素。

队列

跟数组和字典一样,队列也是一种数据结构。队列遵循的规则是先进先出

struct Queue {
    private var array: [T?] = []
    private var head = 0
    
    var isEmpty: Bool {
        return count == 0
    }
    
    var count: Int {
        return array.count - head
    }
    
    mutating func enqueue(_ element: T) {
        array.append(element)
    }
    
    mutating func dequeue() -> T? {
        guard head < array.count,
            let element = array[head] else {
                return nil
        }
        array[head] = nil
        head += 1
        return element
    }
}

extension Queue: Sequence {
    func makeIterator() -> IndexingIterator> {
        let values = array[head..

在队列的实现里面,我们用一个数组来存储队列的元素,并实现了入队和出队的方法。

为了可以使用for-in来遍历队列中的元素,我们要遵循Sequence协议。Sequence协议有两个要求:1)关联值类型,也就是迭代器的类型,在上面的代码中,关联值类型是IndexingIterator,这是所有集合类型的默认迭代器类型。2)实现makeIterator()方法。

使用

struct Person {
    let name: String
}

let lebron = Person(name: "Lebron James")
let love = Person(name: "Kevin Love")
let korver = Person(name: "Kyle Korver")

// 入队
var queue = Queue()
queue.enqueue(lebron)
queue.enqueue(love)
queue.enqueue(korver)

// 出队
queue.dequeue()

for person in queue {
    print(person?.name ?? "此人不存在")
}

// 结果
Kevin Love
Kyle Korver

这里我们定义了一个Person类型,用于定义Person队列。添加了三个人,然后将第一个人剔除,最终剩下两个。

总结

Swift里面有迭代器协议IteratorProtocol,但是我们不需要直接去遵循这个协议,而是通过遵循Sequence来实现,好处是我们不需要自己自定义一个迭代器,而且还可以获得集合的很多方法,例如filtermapsort等等。

欢迎加入我管理的Swift开发群:536353151

下一篇文章:【设计模式】13 - 原型模式 (Prototype Pattern)

你可能感兴趣的:(【设计模式】12 - 迭代器模式 (Iterator Pattern))