迭代器模式入门

迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露结构的底层表示和细节。

在以下情形,考虑使用迭代器模式:

  • 需要访问组合对象的内容,而又不暴露其内部表示
  • 需要通过多种方式遍历组合对象
  • 需要提供一个统一的接口,用来遍历各种类型的组合对象

迭代器模式涉及到以下几个角色:

  • 抽象迭代器(Iterator)角色:此抽象角色定义出遍历元素所需的接口。
  • 具体迭代器(ConcreteIterator)角色:此角色实现了Iterator接口,并保持迭代过程中的游标位置。
  • 聚集(Aggregate)角色:此抽象角色给出创建迭代器(Iterator)对象的接口。
  • 具体聚集(ConcreteAggregate)角色:实现了创建迭代器(Iterator)对象的接口,返回一个合适的具体迭代器实例。
  • 客户端(Client)角色:持有对聚集及其迭代器对象的引用,调用迭代子对象的迭代接口,也有可能通过迭代子操作聚集元素的增加和删除。

UML类图

代码示例

定义迭代器接口和聚集角色:

1
2
3
4
5
6
7
8
9
10
//迭代器接口
protocol Iterator{
func hasNext() -> Bool
func next() -> AnyObject
}

//需要使用迭代器的集合类型需要实现Container,返回一个迭代器对象
protocol Container {
func makeIterator() -> Iterator
}

定义书和书架类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Book {
var name: String
var author: String
init(name: String, author: String) {
self.name = name
self.author = author
}
}

//书架: 书的集合
class Bookrack {
var books: [Book]
init(books: [Book]) {
self.books = books
}
}

定义书架迭代器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//书架迭代器
class BookrackIterator: Iterator {
private let books: [Book]
private var index = 0
init(books: [Book]) {
self.books = books
}

func hasNext() -> Bool {
return index < books.count ? true : false
}

func next() -> AnyObject {
defer {
index += 1
}
return books[index]
}
}

实现具体聚集角色:

1
2
3
4
5
6

extension Bookrack: Container {
func makeIterator() -> Iterator {
return BookrackIterator(books: self.books)
}
}

客户端调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

let book1 = Book(name: "C语言从入门到放弃", author: "C")
let book2 = Book(name: "C++从入门到放弃", author: "C++")
let book3 = Book(name: "Swift从入门到放弃", author: "Swift")
let book4 = Book(name: "Python从入门到放弃", author: "Python")

let bookrack = Bookrack(books: [book1,book2,book3,book4])

let iterator = bookrack.makeIterator()

while(iterator.hasNext()) {
let book = iterator.next() as! Book
print("书名: " + book.name + "作者: " + book.author)
}