迭代器模式 Iterator
提供了一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式的核心思想是将遍历逻辑从聚合对象中分离出来,使得聚合对象和遍历逻辑可以独立变化。
实际应用场景
- 集合类库:
如 Go 的 slice、map 等集合类型,可以通过迭代器模式提供统一的遍历接口。 - 数据库查询结果:
数据库查询结果可以封装为一个聚合对象,并提供迭代器遍历查询结果。 - 文件系统遍历:
文件系统中的目录和文件可以封装为一个聚合对象,并提供迭代器遍历文件系统。 - 树形结构遍历:
树形结构(如二叉树、多叉树)可以提供多种遍历方式(如深度优先、广度优先)。
假设我们有一个集合类 BookCollection,它包含多本书。我们需要实现一个迭代器,用于遍历这个集合
package main
import "fmt"
// Book 定义书籍结构体
type Book struct {
Title string
Author string
}
// Iterator 定义迭代器接口
type Iterator interface {
HasNext() bool
Next() *Book
}
// BookIterator 是具体迭代器
type BookIterator struct {
books []*Book
position int
}
func (b *BookIterator) HasNext() bool {
return b.position < len(b.books)
}
func (b *BookIterator) Next() *Book {
if b.HasNext() {
book := b.books[b.position]
b.position++
return book
}
return nil
}
// Aggregate 定义聚合接口
type Aggregate interface {
CreateIterator() Iterator
}
// BookCollection 是具体聚合
type BookCollection struct {
books []*Book
}
func (b *BookCollection) CreateIterator() Iterator {
return &BookIterator{books: b.books}
}
func main() {
// 创建书籍集合
collection := &BookCollection{
books: []*Book{
{Title: "The Go Programming Language", Author: "Alan A. A. Donovan"},
{Title: "Design Patterns", Author: "Erich Gamma"},
{Title: "Clean Code", Author: "Robert C. Martin"},
},
}
// 创建迭代器
iterator := collection.CreateIterator()
// 遍历集合
for iterator.HasNext() {
book := iterator.Next()
fmt.Printf("Title: %s, Author: %s\n", book.Title, book.Author)
}
}
代码结构分析:
Book结构体:
- 存储书籍信息,包含Title(书名)和Author(作者)两个字段。
Iterator接口:
- 定义迭代器的基本方法:HasNext()(检查是否有下一个元素)和Next()(获取下一个元素)。
BookIterator结构体:
- 实现Iterator接口,包含书籍集合和当前位置索
引。
- HasNext()检查索引是否越界。
- Next()返回当前书籍并移动索引,若无元素则返回nil。
Aggregate接口:
- 定义创建迭代器的方法CreateIterator()。
BookCollection结构体:
- 存储书籍集合,并实现Aggregate接口来返回关联的迭代器。
模式扩展
扩展场景 1:树形结构的遍历
需求:遍历二叉树的不同顺序(前序、中序、后序)
// 树节点结构
type TreeNode struct {
Value int
Left *TreeNode
Right *TreeNode
}
// 前序迭代器
type PreOrderIterator struct {
stack []*TreeNode
}
func NewPreOrderIterator(root *TreeNode) *PreOrderIterator {
if root == nil {
return &PreOrderIterator{stack: []*TreeNode{}}
}
return &PreOrderIterator{stack: []*TreeNode{root}}
}
func (it *PreOrderIterator) HasNext() bool {
return len(it.stack) > 0
}
func (it *PreOrderIterator) Next() *TreeNode {
node := it.stack[len(it.stack)-1]
it.stack = it.stack[:len(it.stack)-1]
if node.Right != nil {
it.stack = append(it.stack, node.Right)
}
if node.Left != nil {
it.stack = append(it.stack, node.Left)
}
return node
}
// 使用示例
func main() {
root := &TreeNode{Value: 1,
Left: &TreeNode{Value: 2},
Right: &TreeNode{Value: 3},
}
it := NewPreOrderIterator(root)
for it.HasNext() {
fmt.Println(it.Next().Value) // 输出 1 2 3
}
}
扩展场景 2:分页遍历大数据集
需求:每次获取N条数据的迭代器
type PageIterator struct {
dataSource func(int, int) []*Book // 模拟数据源函数
pageSize int
currentPage int
offset int
}
func (p *PageIterator) HasNext() bool {
return len(p.dataSource(p.currentPage, p.pageSize)) > 0
}
func (p *PageIterator) Next() []*Book {
chunk := p.dataSource(p.currentPage, p.pageSize)
p.currentPage++
return chunk
}
// 模拟数据库分页查询
func mockDB(page, size int) []*Book {
// 实际场景中这里会连接数据库
return []*Book{{Title: fmt.Sprintf("Book-%d", page)}}
}
func main() {
pager := &PageIterator{
dataSource: mockDB,
pageSize: 10,
}
for pager.HasNext() {
books := pager.Next()
fmt.Println(books) // 分批次获取数据
}
}
扩展场景 3:并发安全迭代器
需求:支持多线程安全遍历
type SafeIterator struct {
mutex sync.Mutex
iterator *BookIterator
}
func (s *SafeIterator) HasNext() bool {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.iterator.HasNext()
}
func (s *SafeIterator) Next() *Book {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.iterator.Next()
}
func main() {
collection := &BookCollection{/* 初始化数据 */}
safeIter := &SafeIterator{
iterator: collection.CreateIterator().(*BookIterator),
}
// 可安全用于goroutine
go func() {
for safeIter.HasNext() {
fmt.Println(safeIter.Next())
}
}()
}
迭代器模式的优势总结
- 解耦遍历逻辑:将数据存储与遍历操作分离
- 支持多种遍历方式:正序/逆序/过滤/分页等
- 简化集合接口:集合只需提供创建迭代器的方法
- 延迟加载支持:特别适合大数据场景的分批加载
- 线程安全扩展:通过封装实现并发控制
这些扩展场景展示了迭代器模式在不同业务需求下的适应能力,适用于文件系统遍历、数据库查询结果处理、网络数据流处理等复杂场景。