/ 设计模式 / 迭代器模式 / Swift Swift 迭代器模式讲解和代码示例 迭代器是一种行为设计模式, 让你能在不暴露复杂数据结构内部细节的情况下遍历其中所有的元素。 在迭代器的帮助下, 客户端可以用一个迭代器接口以相似的方式遍历不同集合中的元素。 进一步了解迭代器模式 导航 简介 概念示例 Example Output 真实世界示例 Example Output 复杂度: 流行度: 使用示例: 该模式在 Swift 代码中很常见。 许多框架和程序库都使用它来提供遍历其集合的标准方式。 识别方法: 迭代器可以通过导航方法 (例如 next和 previous等) 来轻松识别。 使用迭代器的客户端代码可能没有其所遍历的集合的直接访问权限。 以下示例可在 Swift Playgrounds 上使用。 感谢 Alejandro Mohamad 创建了Playground版本。 概念示例 真实世界示例 概念示例 本例说明了迭代器设计模式的结构并重点回答了下面的问题: 它由哪些类组成? 这些类扮演了哪些角色? 模式中的各个元素会以何种方式相互关联? 了解该模式的结构后, 你可以更容易地理解下面基于真实世界的 Swift 应用案例。 Example.swift: 概念示例 import XCTest /// This is a collection that we're going to iterate through using an iterator /// derived from IteratorProtocol. class WordsCollection { fileprivate lazy var items = [String]() func append(_ item: String) { self.items.append(item) } } extension WordsCollection: Sequence { func makeIterator() -> WordsIterator { return WordsIterator(self) } } /// Concrete Iterators implement various traversal algorithms. These classes /// store the current traversal position at all times. class WordsIterator: IteratorProtocol { private let collection: WordsCollection private var index = 0 init(_ collection: WordsCollection) { self.collection = collection } func next() -> String? { defer { index += 1 } return index < collection.items.count ? collection.items[index] : nil } } /// This is another collection that we'll provide AnyIterator for traversing its /// items. class NumbersCollection { fileprivate lazy var items = [Int]() func append(_ item: Int) { self.items.append(item) } } extension NumbersCollection: Sequence { func makeIterator() -> AnyIterator<Int> { var index = self.items.count - 1 return AnyIterator { defer { index -= 1 } return index >= 0 ? self.items[index] : nil } } } /// Client does not know the internal representation of a given sequence. class Client { // ... static func clientCode<S: Sequence>(sequence: S) { for item in sequence { print(item) } } // ... } /// Let's see how it all works together. class IteratorConceptual: XCTestCase { func testIteratorProtocol() { let words = WordsCollection() words.append("First") words.append("Second") words.append("Third") print("Straight traversal using IteratorProtocol:") Client.clientCode(sequence: words) } func testAnyIterator() { let numbers = NumbersCollection() numbers.append(1) numbers.append(2) numbers.append(3) print("\nReverse traversal using AnyIterator:") Client.clientCode(sequence: numbers) } } Output.txt: 执行结果 Straight traversal using IteratorProtocol: First Second Third Reverse traversal using AnyIterator: 3 2 1 真实世界示例 Example.swift: 真实世界示例 import XCTest class IteratorRealWorld: XCTestCase { func test() { let tree = Tree(1) tree.left = Tree(2) tree.right = Tree(3) print("Tree traversal: Inorder") clientCode(iterator: tree.iterator(.inOrder)) print("\nTree traversal: Preorder") clientCode(iterator: tree.iterator(.preOrder)) print("\nTree traversal: Postorder") clientCode(iterator: tree.iterator(.postOrder)) } func clientCode<T>(iterator: AnyIterator<T>) { while case let item? = iterator.next() { print(item) } } } class Tree<T> { var value: T var left: Tree<T>? var right: Tree<T>? init(_ value: T) { self.value = value } typealias Block = (T) -> () enum IterationType { case inOrder case preOrder case postOrder } func iterator(_ type: IterationType) -> AnyIterator<T> { var items = [T]() switch type { case .inOrder: inOrder { items.append($0) } case .preOrder: preOrder { items.append($0) } case .postOrder: postOrder { items.append($0) } } /// Note: /// AnyIterator is used to hide the type signature of an internal /// iterator. return AnyIterator(items.makeIterator()) } private func inOrder(_ body: Block) { left?.inOrder(body) body(value) right?.inOrder(body) } private func preOrder(_ body: Block) { body(value) left?.inOrder(body) right?.inOrder(body) } private func postOrder(_ body: Block) { left?.inOrder(body) right?.inOrder(body) body(value) } } Output.txt: 执行结果 Tree traversal: Inorder 2 1 3 Tree traversal: Preorder 1 2 3 Tree traversal: Postorder 2 3 1 概念示例 真实世界示例