当前位置: 首页 > news >正文

[go] 迭代器模式

迭代器模式

提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露其内部的表示。

模型说明

  • Iterator: 接口声明了遍历集合所需的操作: 获取下一个元素、 获取当前位置和重新开始迭代等。

  • IterableCollection: 接口声明一个或多个方法来获取与集合兼容的迭代器。 请注意, 返回方法的类型必须被声明为迭代器接口, 因此具体集合可以返回各种不同种类的迭代器。

  • ConcreteIterator: 实现遍历集合的一种特定算法。 迭代器对象必须跟踪自身遍历的进度。 这使得多个迭代器可以相互独立地遍历同一集合。

  • ConcreteCollection: 会在客户端请求迭代器时返回一个特定的具体迭代器类实体。 你可能会琢磨, 剩下的集合代码在什么地方呢? 不用担心, 它也会在同一个类中。 只是这些细节对于实际模式来说并不重要, 所以我们将其省略了而已。

  • Client: 通过集合和迭代器的接口与两者进行交互。 这样一来客户端无需与具体类进行耦合, 允许同一客户端代码使用各种不同的集合和迭代器。

  • 客户端通常不会自行创建迭代器, 而是会从集合中获取。 但在特定情况下, 客户端可以直接创建一个迭代器 (例如当客户端需要自定义特殊迭代器时)。

优缺点

1.优点

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

2.缺点

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

使用场景

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

参考代码

// iterator.go 迭代器接口
type Iterator interface {hasNext() boolgetNext() *User
}
// userIterator.go 具体迭代器
type UserIterator struct {index intusers []*User
}func (u *UserIterator) hasNext() bool {if u.index < len(u.users) {return true}return false
}func (u *UserIterator) getNext() *User {if u.hasNext() {user := u.users[u.index]u.index++return user}return nil
}
// collection.go 集合接口
type Collection interface {createIterator() Iterator
}
// userCollection.go 具体集合
type User struct {name stringage  int
}type UserCollection struct {users []*User
}func (u *UserCollection) createIterator() Iterator {return &UserIterator{users: u.users,}
}
// main.go 客户端
func main() {user1 := &User{name: "a",age:  30,}user2 := &User{name: "b",age:  20,}userCollection := &UserCollection{users: []*User{user1, user2},}iterator := userCollection.createIterator()for iterator.hasNext() {user := iterator.getNext()fmt.Printf("User is %+v\n", user)}
}

output:

User is &{name:a age:30}
User is &{name:b age:20}

相关文章:

  • Android双击图片放大移动图中双击点到ImageView区域中心,Kotlin
  • 回溯法:N皇后问题
  • 【PGSQL】date_trunc 函数
  • 【导航】繁星学习随想录
  • 了解Vue中日历插件Fullcalendar
  • Elasticsearch 分布式架构剖析及扩展性优化
  • 初识计算机图形学
  • openssl3.2 - 官方demo学习 - mac - poly1305.c
  • CSS 设置背景图片
  • 【JavaEE】网络原理:网络中的一些基本概念
  • AI+量化02_金融市场的基础概念
  • 蓝桥oj3272小蓝的漆房
  • 【SpringCloud】微服务框架后端部署详细过程记录20240119
  • Unity - transform使用
  • C++核心编程
  • 【翻译】babel对TC39装饰器草案的实现
  • 77. Combinations
  • Android系统模拟器绘制实现概述
  • Fabric架构演变之路
  • java中具有继承关系的类及其对象初始化顺序
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • mongo索引构建
  • node学习系列之简单文件上传
  • python docx文档转html页面
  • SpiderData 2019年2月25日 DApp数据排行榜
  • Spring Cloud Feign的两种使用姿势
  • vue--为什么data属性必须是一个函数
  • 程序员最讨厌的9句话,你可有补充?
  • 工作手记之html2canvas使用概述
  • 简单基于spring的redis配置(单机和集群模式)
  • 马上搞懂 GeoJSON
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 删除表内多余的重复数据
  • 使用putty远程连接linux
  • 微信公众号开发小记——5.python微信红包
  • 携程小程序初体验
  • 怎么把视频里的音乐提取出来
  • !$boo在php中什么意思,php前戏
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (NSDate) 时间 (time )比较
  • (poj1.3.2)1791(构造法模拟)
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (二十四)Flask之flask-session组件
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (七)Java对象在Hibernate持久化层的状态
  • *p++,*(p++),*++p,(*p)++区别?
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .NET : 在VS2008中计算代码度量值
  • .Net Core 中间件验签
  • .NET Standard 支持的 .NET Framework 和 .NET Core