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

【设计模式-4.5】行为型——迭代器模式 - 教程

【设计模式-4.5】行为型——迭代器模式 - 教程

说明:本文介绍设计模式中,行为型设计模式之一的迭代器模式。

定义

迭代器模式(Iterator Pattern),也叫作游标模式(Cursor Pattern),它提供一种按顺序访问集合/容器对象元素的方法,而又无须暴露集合内部表示。迭代器模式可以为不同的容器提供一致的遍历行为,而不用关心容器内元素的组成结构。(引自《设计模式就该这样学》P329)

行车记录仪场景

假设有一个行车记录仪对象,可存储行车记录时的视频,可存储10个视频,超出会覆盖最早的数据,如下:

/**
* 行车记录仪
*/
public
class DrivingRecorder {
/**
* 当前记录的位置
*/
private
int index = -1
;
/**
* 假设只能存储10个视频
*/
private String[] records =
new String[10]
;
/**
* 存入
*/
public
void append(String record) {
// 如果当前位置已经到达末尾,就从头开始存储
if (index == 9
) {
index = 0
;
}
else {
index++
;
}
records[index] = record;
}
/**
* 顺序遍历
*/
public
void display(
) {
for (
int i = 0
; i <
10
; i++
) {
System.out.println(i + ":" + records[i]
)
;
}
}
/**
* 按照存入顺序逆序遍历
* 从新=>旧读取
*/
public
void displayByOrder(
) {
// loopCount:是集合能存储的数据个数,故不能大于10;
// i是记录的位置,存的时候+1,读的时候-1,并且还要做==0判断,如果==0,就从集合末尾开始读;
for (
int i = index, loopCount = 0
; loopCount <
10
; i = i == 0 ? 9 : i - 1
, loopCount++
) {
System.out.println(records[i]
)
;
}
}
}

运行如下,可见存入12个视频,把前面存储的两个视频数据覆盖了。

在这里插入图片描述

分析
(1)无法读取到行车记录仪中的数据(即变量records),当然我们可以开放对应的get方法,但这样设计遍历和读取数据方法不免有重复(现成的index变量还没用上,不可惜嘛?),我们能否扩展遍历方法,返回当前位置上的数据?;

(2)代码不够优雅,对于一个封闭的对象或者说容器,遍历对象内的数据,我们是否可以考虑抽出成一个接口,定义遍历的规范,使其他对象实现其接口。

迭代器设计

针对上面行车记录仪场景,改造成迭代器设计模式,如下:

import java.util.Iterator
;
/**
* 行车记录仪(迭代器设计)
*/
public
class DrivingRecorderIterable
implements Iterable<
String> {
/**
* 当前记录的位置
*/
private
int index = -1
;
/**
* 假设只能存储10个视频
*/
private String[] records =
new String[10]
;
/**
* 存入
*/
public
void append(String record) {
// 如果当前位置已经到达末尾,就从头开始存储
if (index == 9
) {
index = 0
;
}
else {
index++
;
}
records[index] = record;
}
@Override
public Iterator<
String> iterator(
) {
return
new Itr(
)
;
}
/**
* 行车记录仪迭代器
*/
private
class Itr
implements Iterator<
String> {
/**
* cursor:游标,这里通过赋值拷贝一份,不要直接使用index,不然一边读一边写的时候会出错
* loopCount:是集合能存储的数据个数,故不能大于10
*/
int cursor = index;
int loopCount = 0
;
@Override
public
boolean hasNext(
) {
return loopCount <
10
;
}
@Override
public String next(
) {
int i = cursor;
if (i == 9
) {
i = 0
;
}
else {
i++
;
}
cursor = i;
loopCount++
;
return records[i]
;
}
}
}

这里使用的接口是JDK自带的Iterator,实现该接口的类都能使用上述方式遍历数据。

在这里插入图片描述

Java中的单列集合,Collection,实现了该接口,也就是说实现了Collection接口的容器,都支持这种迭代器的遍历方式。

在这里插入图片描述

像ArrayList

List<
String> list =
new ArrayList<
>(
)
;
list.add("王麻子"
)
;
list.add("小李子"
)
;
list.add("李爱花"
)
;
Iterator<
String> iterator = list.iterator(
)
;
while (iterator.hasNext(
)
){
System.out.println(iterator.next(
)
)
;
}

使用场景

在《设计模式就该这样学》(P330)这本书中,提到迭代器模式适用于以下场景:

(1)访问一个集合对象的内容而无须暴露它的内部表示。

(2)为遍历不同的集合结构提供一个统一的访问接口;


结合上述行车记录仪场景,如果你需要访问一个对象中的数据,又不想开放对应数据的get方法,就可以考虑迭代器模式。

总结

本文介绍了行为型设计模式中的迭代器模式,参考《设计模式就该这样学》、《秒懂设计模式》两书,行车记录仪场景是《秒懂设计模式》中的举例,非常形象,容易理解。

http://www.hskmm.com/?act=detail&tid=25662

相关文章:

  • 循环结构
  • SP6950 CTOI10D3 - A HUGE TOWER 题解
  • 浅谈并查集
  • 16_AiAgentMCP简单教程
  • 17_AiAgentMCP实现技术选型
  • JVM_XMS 和 java_opts哪种写法对?如何在JVM中设置JVM_XMS和java_opts?
  • POLIR-Society-Philosophy-mind: 思想/精神
  • 鸿蒙编译ffmpeg库 - 详解
  • 知道却做不到
  • 题解:loj154 集合划分计数
  • 为什么 Java 中打印Object类型的变量无需强转,而从Object类型的数组中取元素却要强转?
  • WinReanimator恶意软件清除指南:详细步骤与工具使用
  • 251006
  • 2025国庆Day5
  • 字节跳动开源图标库:2000+图标一键换肤的魔法 - 教程
  • 换根DP学习笔记
  • 自动化数据操作平台获3000万美元融资
  • 模块
  • 实用指南:【相机基础知识与物体检测】更新中
  • AtCoder Beginner Contest 422 游记(VP)
  • 详细介绍:无人机光纤FC接口模块技术分析
  • 2025 --【J+S 二十连测】-- 第十三套 总结
  • 文件提供的基本操作
  • 深入解析:MySQL(50)如何使用UNSIGNED属性?
  • 迈向人机价值共生文明:AI元人文范式下的演化架构与协同治理
  • 10.6
  • 文件存储空间管理
  • 详细介绍:关于ios点击分享自动复制到粘贴板的问题
  • 新一代数据平台替代传统大数据技术栈
  • 攻击者如何绕过macOS内置安全防护机制