设计模式笔记 - 迭代器模式

199 阅读2分钟

迭代器模式是一种行为设计模式,让你能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素。


解决什么问题?

  • 当集合背后为复杂的数据结构, 且你希望对客户端隐藏其复杂性时 (出于使用便利性或安全性的考虑), 可以使用迭代器模式。
  • 如果你希望代码能够遍历不同的甚至是无法预知的数据结构, 可以使用迭代器模式。

优势:

  • 单一职责原则。 通过将体积庞大的遍历算法代码抽取为独立的类, 你可对客户端代码和集合进行整理。
  • 开闭原则。 你可实现新型的集合和迭代器并将其传递给现有代码, 无需修改现有代码。
  • 你可以并行遍历同一集合, 因为每个迭代器对象都包含其自身的遍历状态。
  • 相似的, 你可以暂停遍历并在需要时继续。

劣势:

  • 如果你的程序只与简单的集合进行交互, 应用该模式可能会矫枉过正。
  • 对于某些特殊集合, 使用迭代器可能比直接遍历的效率低。

实现步骤:

  • 定义迭代器接口
  • 定义实体迭代器类,实现迭代器接口
  • 定义迭代器工厂接口,用于获取不同的迭代器
  • 实体集合类实现迭代器工厂接口

实现代码:

package main

import "fmt"

// 定义迭代器接口
type iterator interface {
	getNext() int
	hasMore() bool
}

// 定义迭代器工厂接口
type iterable interface {
	intoIterator(isForward bool) iterator
}

// 实体集合类
type collection struct {
	c []int
}

func (c *collection) get(index int) int {
	return c.c[index]
}

func (c *collection) len() int {
	return len(c.c)
}

func (c *collection) intoIterator(isForward bool) iterator {
	if isForward {
		return &forwardIterator{
			cur: 0,
			c:   c,
		}
	}

	return &backwardIterator{
		cur: len(c.c) - 1,
		c:   c,
	}
}

// 实体迭代器类
type forwardIterator struct {
	cur int
	c   *collection
}

func (f *forwardIterator) getNext() int {
	f.cur += 1
	return f.c.get(f.cur - 1)
}

func (f *forwardIterator) hasMore() bool {
	if f.cur >= f.c.len() {
		return false
	}
	return true
}

// 实体迭代器类
type backwardIterator struct {
	cur int
	c   *collection
}

func (b *backwardIterator) getNext() int {
	b.cur -= 1
	return b.c.get(b.cur + 1)
}

func (b *backwardIterator) hasMore() bool {
	if b.cur < 0 {
		return false
	}
	return true
}

func main() {
	cl := collection{
		c: []int{1, 2, 3, 4},
	}

	fi := cl.intoIterator(true)
	for fi.hasMore() {
		fmt.Println(fi.getNext())
	}

	bi := cl.intoIterator(false)
	for bi.hasMore() {
		fmt.Println(bi.getNext())
	}
}

输出:

1
2
3
4
4
3
2
1

参考