定义

迭代器模式是一种行为模式, 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴漏该对象的内部表示。

简单来讲,for range

UML类图

迭代器模式的主要思想是对集合背后的迭代逻辑提取

iterator1

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 迭代器接口
type IIterator interface {
	Value() interface{}
	HasNext() bool
	Next()
}

// 容器接口
type IAggregate interface {
	Iterator() IIterator
}

// 具体容器
type Aggregate struct {
	container []interface{} // 容器
}

// 创建一个迭代器,并让迭代器中的容器指针指向当前对象
func (a *Aggregate) Iterator() IIterator {
	i := new(Iterator)
	i.aggregate = a
	return i
}

// 实现迭代器
type Iterator struct {
	index     int        // 当前游标
	aggregate *Aggregate // 对应的容器指针
}

// 获取当前迭代元素(从容器中取出当前游标对应的元素)
func (i *Iterator) Value() interface{} {
	return i.aggregate.container[i.index]
}

// 判断是否迭代到最后,如果没有,则返回true
func (i *Iterator) HasNext() bool {
	return i.index+1 < len(i.aggregate.container)
}

// 将游标指向下一个元素
func (i *Iterator) Next() {
	if i.index < len(i.aggregate.container) {
		i.index++
	}
}

func main() {
	// 创建容器,并放入初始化数据
	c := &Aggregate{container: []interface{}{1, 2, 3, 4}}
	// 获取迭代器
	iterator := c.Iterator()

	// 迭代遍历数据
	for iterator.HasNext() {
		fmt.Println(iterator.Value())
		iterator.Next()
	}
}

使用场景

  • 当集合背后为复杂的数据结构,可以使用迭代器模式屏蔽复杂性

  • 代码复用, 可以减少代码中重复的遍历代码

总结

优点:

  • 单一职责原则, 只进行遍历

  • 开闭原则, 可以为任何新集合进行遍历,无需修改现有代码

  • 支持多种不同的方式遍历一个聚合对象:顺序,逆序等

  • 可以暂停遍历,并在需要时继续. for只能一次性全部遍历

缺点:

  • 增加了系统复杂性,需要添加新的迭代器类
  • 性能可能不如直接遍历

思考题: 下面这个是迭代器模式吗,为什么?

UML类图

iterator2

示例代码

cat iterator.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type Iterator interface {
	Value() interface{}
	HasNext() bool
	Next()

	// Index()
	// Next()
	// Prev()
	// ToBegin()
	// ToEnd()
}

cat collection.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
type ArrayIterator struct {
	Index int
	Array []interface{}
}

func (a *ArrayIterator) Value() interface{} {
	return a.Array[a.Index]
}

func (a *ArrayIterator) HasNext() bool {
	return a.Index+1 <= len(a.Array)
}

func (a *ArrayIterator) Next() {
	if a.HasNext() {
		a.Index++
		//atomic.AddInt64(&a.index,1)
	}
}

cat iterator_test1.go

func TestArrayIterator(t *testing.T) {
	// 1. 构建迭代器
	array := []interface{}{3, 5, 7, 2, 4, 6}
	iterator := ArrayIterator{Array: array}
	//iterator := ArrayIterator{array: array}

	// 2. 遍历迭代器
	for it := iterator; it.HasNext();it.Next() {
		num := it.Value()
		fmt.Println(num)
	}
}

cat iteror_test2.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
type User struct {
	name string
	age  int
	sex  int // 0未知, 1男, 2女
}


func TestArrayIterator_user(t *testing.T) {
	// 1. 构建迭代器
	user1 := User{"a", 18, 1}
	user2 := User{"b", 20, 2}
	array := []interface{}{user1, user2}

	//// 排序
	//sort.Slice(array, func(i, j int) bool {
	//	return array[i].(User).age < array[j].(User).age
	//})
	//// 过滤
	//filter(&array, func(u interface{}) bool {
	//	return u.(User).sex == 0
	//})

	iterator := ArrayIterator{Array: array}

	// 2. 遍历迭代器
	for it := iterator; it.HasNext(); it.Next() {
		user := it.Value()
		fmt.Println(user.(User).age)
	}
}

func filter(array *[]interface{}, f func(u interface{}) bool) {
	for k, v := range *array {
		if !f(v) {
			*array = append((*array)[:k], (*array)[k+1:]...)
		}
	}
	fmt.Println(array)
}