100行代码实现迭代器模式,开箱即用


迭代器模式介绍

迭代器模式定义 迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

简单理解:对容器内元素遍历 2.迭代器模式角色划分 迭代器角色(Iterator):定义遍历元素所需要的方法,一般来说会有这么三个方法:取得下一个元素next(),判断是否遍历结束的方法hasNext(),移除当前对象的方法remove()。 具体迭代器角色(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代。 容器角
色(Aggregate):一般是一个接口,提供一个iterator()方法

角色

  • 抽象聚合类: 定义一个抽象的容器

  • 具体聚合类: 实现上面的抽象类,作为一个容器,用来存放元素,等待迭代

  • 抽象迭代器: 迭代器接口,每个容器下都有一个该迭代器接口的具体实现

  • 具体迭代器: 根据不同的容器,需要定义不同的具体迭代器,定义了游标移动的具体实现

代码结构

├── aggregate.go // 集合接口定义和实现。定义了`NewIterator`、`Data`两个函数
├── aggregate_test.go // 单测
├── go.mod
├── go.sum
└── iterator.go // 迭代器接口定义和实现。

代码解析

聚合接口和定义

type Aggregate[T any] interface {
   NewIterator() Iterator[T]
}

接口定义比较简单,NewIterator方法表示基于当前聚合对象生成一个迭代器

聚合接口的实现

type aggregate[T any] struct {
   data []T
}

func NewAggregate[T any](data []T) Aggregate[T] {
   return &aggregate[T]{
      data: data,
   }
}

func (aggr *aggregate[T]) NewIterator() Iterator[T] {
   return newIterator[T](aggr)
}

迭代器接口定义和实现

type Iterator[T any] interface {
   // First 第一个元素
   First() T
   // MoveToFirst 移动到第一个元素
   MoveToFirst()
   // Last 最后一个元素
   Last() T
   // MoveToLast 移动到最后一个元素
   MoveToLast()
   // HasNext 是否还有下一个元素
   HasNext() bool
   // Next 获取下一个元素
   Next() T
   // Current 获取当前元素
   Current() T
   // Reverse 翻转
   Reverse()
   // Empty 集合是否为空
   Empty() bool
   // Delete 移除当前元素
   Delete() T
   // Count 元素数量
   Count() int
}

迭代器接口定义的方法比较多,但是比较简单,下面看看具体的视线

type iterator[T any] struct {
   pointer   int  // 当前指针
   dataArray []any // 集合中的元素,这里定义的是[]any,因为[]T类型不能使用len函数。并且为了不影响集合中的元素,这里重新定义了一个集合
   reverse   bool // 翻转,表示将当前集合中的元素做180翻转,方便从后往前迭代
   count     int // 集合中元素数量
}

func newIterator[T any](aggr *aggregate[T]) Iterator[T] {
   i := &iterator[T]{
      pointer: 0,
   }

   for _, data := range aggr.data {
      i.dataArray = append(i.dataArray, data)
   }

   i.count = len(i.dataArray)

   return i
}

func (i *iterator[T]) First() T {
   return i.dataArray[0].(T)
}

func (i *iterator[T]) MoveToFirst() {
   i.pointer = 0
}

func (i *iterator[T]) Last() T {
   return i.dataArray[i.count-1].(T)
}

func (i *iterator[T]) MoveToLast() {
   i.pointer = i.count - 1
}

func (i *iterator[T]) HasNext() bool {
   return i.pointer < i.count-1
}

func (i *iterator[T]) Next() T {
   if !i.HasNext() {
      zeroVal := new(T)
      return *zeroVal
   }

   i.pointer += 1
   return i.Current()
}

func (i *iterator[T]) Current() T {
   return i.dataArray[i.pointer].(T)
}

func (i *iterator[T]) Reverse() {
   newDataAny := make([]any, i.count)
   for idx := i.count - 1; idx >= 0; idx-- {
      newDataAny[i.count-1-idx] = i.dataArray[idx]
   }
   i.dataArray = newDataAny
   i.pointer = i.count - 1 - i.pointer

   i.reverse = !i.reverse
}

func (i *iterator[T]) Empty() bool {
   return i.count == 0
}

func (i *iterator[T]) Delete() (deleteData T) {
   if i.Empty() {
      return
   }

   newData := make([]any, 0, i.count)
   for idx := range i.dataArray {
      if idx == i.pointer {
         deleteData = i.dataArray[idx].(T)
         continue
      }
      newData = append(newData, i.dataArray[idx])
   }
   i.count--
   i.dataArray = newData
   if i.pointer >= i.count {
      i.pointer -= 1
   }
   return
}

func (i *iterator[T]) Count() int {
   return i.count
}

源代码:https://github.com/ZBIGBEAR/iterator/tree/main

参考

[1]迭代器模式

[2]golang设计模式之迭代器模式


文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
  目录