Go语言设计模式之迭代器模式Iterator

迭代器模式 Iterator

提供了一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式的核心思想是将遍历逻辑从聚合对象中分离出来,使得聚合对象和遍历逻辑可以独立变化。

实际应用场景

  1. 集合类库:
    如 Go 的 slice、map 等集合类型,可以通过迭代器模式提供统一的遍历接口。
  2. 数据库查询结果:
    数据库查询结果可以封装为一个聚合对象,并提供迭代器遍历查询结果。
  3. 文件系统遍历:
    文件系统中的目录和文件可以封装为一个聚合对象,并提供迭代器遍历文件系统。
  4. 树形结构遍历:
    树形结构(如二叉树、多叉树)可以提供多种遍历方式(如深度优先、广度优先)。

假设我们有一个集合类 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())
        }
    }()
}

迭代器模式的优势总结

  • 解耦遍历逻辑:将数据存储与遍历操作分离
  • 支持多种遍历方式:正序/逆序/过滤/分页等
  • 简化集合接口:集合只需提供创建迭代器的方法
  • 延迟加载支持:特别适合大数据场景的分批加载
  • 线程安全扩展:通过封装实现并发控制

这些扩展场景展示了迭代器模式在不同业务需求下的适应能力,适用于文件系统遍历、数据库查询结果处理、网络数据流处理等复杂场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值