【Go-设计模式】迭代器模式 详解

概念:
迭代器模式(Iterator Pattern)是常用的设计模式,属于 行为型模式
当 客户端 要 遍历这些集合元素 的时候,就需要使用 多种遍历方式,而且还会 暴露元素的内部结构,可以考虑使用迭代器模式解决
迭代器模式,提供一种 遍历集合元素 的 统一接口,用 一致的方法 遍历集合元素,不需要知道 集合对象的 底层表示,即:不暴露其内部的结构
可以使用迭代器模式使遍历同时 应用迭代策略,如 请求新对象、过滤、处理对象 等。

UML:

- Iterator:
迭代器接口,供客户端 遍历集合 使用 - ConcreteIterator:
具体的迭代器类,迭代集合的 具体实现 - Aggregate:
统一的聚合接口, 将 客户端 和 具体聚合 进行 解耦 - ConcreteAggreage:
具体的聚合持有对象集合, 并提供 一个方法,返回 一个迭代器, 该迭代器可以 正确遍历集合
示例:
迭代器 功能接口:
type Iterator interface {
HashNext() bool
Next() interface{}
Remove()
}
具体的迭代器类:
具体的迭代器类1:
type ConcreteIterator struct {
eleList []string
offset int
}
func (this *ConcreteIterator) HashNext() bool {
if this.offset < len(this.eleList) {
return true
}
return false
}
func (this *ConcreteIterator) Next() interface{} {
element := this.eleList[this.offset]
this.offset += 1
return element
}
func (this *ConcreteIterator) Remove() {
index := copy(this.eleList[this.offset:], this.eleList[this.offset+1:])
this.eleList = this.eleList[:this.offset+index]
}
func NewConcreteIterator(eleList []string) *ConcreteIterator {
return &ConcreteIterator{
eleList: eleList,
}
}
具体的迭代器类2:
type ConcreteIterator2 struct {
eleMap map[int64]string
key int64
}
func (this *ConcreteIterator2) HashNext() bool {
if this.key < int64(len(this.eleMap)) {
return true
}
return false
}
func (this *ConcreteIterator2) Next() interface{} {
element := this.eleMap[this.key]
this.key += 1
return element
}
func (this *ConcreteIterator2) Remove() {
delete(this.eleMap, this.key)
}
func NewConcreteIterator2(eleMap map[int64]string) *ConcreteIterator2 {
return &ConcreteIterator2{
eleMap: eleMap,
}
}
聚合接口:
type Aggregate interface {
Iterator() Iterator
}
具体的聚合类
具体的聚合类1:
type ConcreteAggregate struct {
eleList []string
}
func (this *ConcreteAggregate) Iterator() Iterator {
return NewConcreteIterator(this.eleList)
}
func (this *ConcreteAggregate) AddElement(info string) {
this.eleList = append(this.eleList, info)
}
func NewConcreteAggregate() ConcreteAggregate {
return ConcreteAggregate{
eleList: []string{},
}
}
具体的聚合类2:
type ConcreteAggregate2 struct {
eleMap map[int64]string
}
func (this *ConcreteAggregate2) Iterator() Iterator {
return NewConcreteIterator2(this.eleMap)
}
func (this *ConcreteAggregate2) AddKv(key int64, value string) {
this.eleMap[key] = value
}
func NewConcreteAggregate2() ConcreteAggregate2 {
return ConcreteAggregate2{
eleMap: map[int64]string{},
}
}
测试:
package main
import (
"DemoProject/design/base23/iterator" // 根据自己的项目路径定制
"fmt"
)
func main() {
// iterator
// ============== type1 ==================
aggregate1 := iterator.NewConcreteAggregate1()
aggregate1.AddElement("youzg")
aggregate1.AddElement("is")
aggregate1.AddElement("a")
aggregate1.AddElement("good")
aggregate1.AddElement("man")
aggregate1.AddElement("!")
iterator1 := aggregate1.Iterator()
iterator1.Remove()
for iterator1.HashNext() {
fmt.Println(iterator1.Next())
}
// ============== type2 ==================
aggregate2 := iterator.NewConcreteAggregate2()
aggregate2.AddKv(0, "and")
aggregate2.AddKv(1, "he")
aggregate2.AddKv(2, "is")
aggregate2.AddKv(3, "so")
aggregate2.AddKv(4, "cool")
aggregate2.AddKv(5, "!")
iterator2 := aggregate2.Iterator()
iterator2.Remove()
for iterator2.HashNext() {
fmt.Println(iterator2.Next())
}
}
个人总结,就是封装集合类的操作接口,
使得不管是什么 数据结构,都用的是 同一套SDK 去操作
注意事项:
优点:
提供一个 统一的方法 遍历对象,Client 不用再考虑 聚合的类型,使用 一种方法 就可以 遍历对象 了
隐藏了 聚合的内部结构,客户端要 遍历聚合 的时候只能 取到迭代器,而 不会知道 聚合 的 具体组成
提供了一种 设计思想,就是 一个类 应该 只有一个引起变化的原因(单一责任原则)
在 聚合类 中,我们把 迭代器 分开,就是要把 管理对象集合 和 遍历对象集合 的 责任 分开,
这样一来 集合改变 的话,只影响到 聚合对象;而如果 遍历方式改变 的话,只影响到了 迭代器
当要 展示一组相似对象,或者 遍历一组相同对象时, 适合使用 迭代器模式
缺点:
每个聚合对象 都要 一个迭代器,会生成 多个迭代器,不方便类之间的管理

浙公网安备 33010602011771号