简介

迭代器模式(Iterator Pattern),是一种结构型设计模式。给数据对象构建一套按顺序访问集合对象元素的方式,而不需要知道数据对象的底层表示。

迭代器模式是与集合共存的,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像Java中的Collection,List、Set、Map等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,就可以引入迭代器模式,给我们的容器实现一个迭代器。

作用

  1. 可以提供多种遍历对象的方式,把元素之间查找调用的责任交给迭代器,而不是聚合对象。
  2. 分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。

实现步骤

  1. 创建迭代器接口,定义hasNext()和next()方法
  2. 创建数据容器接口,用来创建迭代器
  3. 创建具体数据列表,实现数据容器接口,可以创建迭代器,内含数据列表对象
  4. 创建某种数据对象的迭代器,实现hasNext()以及next()方法,并且关联上数据对象列表

UML

Java代码

迭代器抽象接口


// Iterator.java 迭代器抽象接口,提供next和hasNext方法
public interface Iterator {
public boolean hasNext();
public Object next();
}

具体迭代器

// ObjectIterator.java 对象迭代器,实现了抽象迭代器的方法,聚合了对象列表
public class ObjectIterator implements Iterator { private ObjectList objectList; int index; public ObjectIterator(ObjectList objectList) {
this.objectList = objectList;
} @Override
public boolean hasNext() {
if (index < objectList.size()) {
return true;
}
return false;
} @Override
public Object next() {
if (this.hasNext()) {
// 返回数据对象提供的get方法,每访问一次则增加下标
return objectList.get(index++);
}
return null;
}
}

数据容器接口

// Container.go 创建抽象容器接口,创建一个迭代器
public interface Container {
public Iterator createIterator();
}

具体数据对象

// ObjectList.java 对象列表,是一种数据容器,可以创建一个迭代器
public class ObjectList implements Container {
private Object[] objects = { "Google", "Apple", "Amazon" }; @Override
public Iterator createIterator() {
System.out.println(this.getClass().getName() + "::createIterator() [获取迭代器 ObjectIterator]");
// 把当前对象传给迭代器
return new ObjectIterator(this);
} public void setObjects(Object[] objects) {
this.objects = objects;
} public int size() {
return objects.length;
} public Object get(int index) {
return objects[index];
}
}

测试调用

    /*
* 迭代器模式是给数据容器创建单独的迭代器,用来遍历里面的数据对象
* 数据容器和迭代器相互关联,外部通过迭代器来访问数据容器
* 通过这种方式由迭代器类来负责数据遍历,这样可以做到不暴露集合的内部结构
*/ int i = 0;
ObjectList objectList = new ObjectList();
objectList.setObjects(new String[] { "Thomas", "Merry", "Jack", "Tony", "Jerry", "Joey" });
// for循环迭代对象
for (Iterator iter = objectList.createIterator(); iter.hasNext();) {
String name = (String) iter.next();
System.out.println("objectList[" + i + "] = " + name);
i++;
} // while循环迭代对象
Iterator iter2 = objectList.createIterator();
objectList.setObjects(new Integer[] { 3, 5, 7, 9, 11 });
while (iter2.hasNext()) {
System.out.println(iter2.next());
}

Go代码

迭代器抽象接口

// Iterator.go 迭代器抽象接口,提供next和hasNext方法
type Iterator interface {
HasNext() bool
Next() string
}

具体迭代器

// ObjectIterator.go 对象迭代器,实现了抽象迭代器的方法,聚合了对象列表
type ObjectIterator struct {
// 迭代器索引
index int
// 聚合了数据对象
objectList *ObjectList
} func (o *ObjectIterator) HasNext() bool {
if o.index < o.objectList.Size() {
return true
}
return false
} func (o *ObjectIterator) Next() string {
if o.HasNext() {
// 返回数据对象提供的get方法,每访问一次下标增加1位
item := o.objectList.Get(o.index)
o.index += 1
return item
}
return ""
}

数据容器接口

// Container.go 创建抽象容器接口,创建一个迭代器
type Container interface {
CreateIterator() Iterator
}

具体数据对象

// ObjectList.go 对象列表,是一种数据容器,可以创建一个迭代器
type ObjectList struct {
// 内部的数据结构
objects []string
} func (o *ObjectList) CreateIterator() Iterator {
fmt.Println("ObjectList::CreateIterator() [获取迭代器 ObjectIterator]")
// 创建迭代器实例,绑定新建当前对象
return &ObjectIterator{
objectList: o,
}
} func (o *ObjectList) SetObjects(objects []string) {
o.objects = objects
} func (o *ObjectList) GetObjects() []string {
return o.objects
} func (o *ObjectList) Size() int {
return len(o.objects)
} func (o *ObjectList) Get(index int) string {
return o.objects[index]
}

测试调用

    /*
* 迭代器模式是给数据容器创建单独的迭代器,用来遍历里面的数据对象
* 数据容器和迭代器相互关联,外部通过迭代器来访问数据容器
* 通过这种方式由迭代器类来负责数据遍历,这样可以做到不暴露集合的内部结构
*/ int i = 0;
ObjectList objectList = new ObjectList();
objectList.setObjects(new String[] { "Thomas", "Merry", "Jack", "Tony", "Jerry", "Joey" });
// for循环迭代对象
for (Iterator iter = objectList.createIterator(); iter.hasNext();) {
String name = (String) iter.next();
System.out.println("objectList[" + i + "] = " + name);
i++;
} // while循环迭代对象
Iterator iter2 = objectList.createIterator();
objectList.setObjects(new Integer[] { 3, 5, 7, 9, 11 });
while (iter2.hasNext()) {
System.out.println(iter2.next());
}

C语言简版

#include <stdio.h>
#include <stdlib.h> // 简单版C语言迭代器模式,自己构建List数据类型 // 数据结构,这里使用链表作为示例
struct List
{
char *data;
struct List *next;
}; // 迭代器结构体
struct Iterator
{
struct List *current;
int (*has_next)(struct Iterator *); // 判断是否还有下一个元素
char *(*next)(struct Iterator *, char **); // 获取下一个元素
}; // 判断是否还有下一个元素
int has_next(struct Iterator *iter)
{
return iter->current != NULL;
} // 获取下一个元素
char *next(struct Iterator *iter, char **value)
{
if (iter->current == NULL)
{
return NULL;
}
*value = iter->current->data;
iter->current = iter->current->next;
return *value;
} // 初始化迭代器
void create_iterator(struct Iterator *iter, struct List *head)
{
iter->current = head;
iter->has_next = &has_next;
iter->next = &next;
} // 遍历链表
void iterate_list(struct List *head)
{
struct Iterator iter;
char *value;
create_iterator(&iter, head);
while (iter.has_next(&iter))
{
iter.next(&iter, &value);
printf("\r\n %s ", value);
}
printf("\n");
} int main()
{
printf("test start:\r\n");
// 构造一个链表
struct List *head = (struct List *)malloc(sizeof(struct List));
head->data = "Tom";
head->next = (struct List *)malloc(sizeof(struct List));
head->next->data = "Jerry";
head->next->next = (struct List *)malloc(sizeof(struct List));
head->next->next->data = "Max";
head->next->next->next = NULL; // 使用迭代器遍历链表
iterate_list(head); // 释放链表内存
while (head != NULL)
{
struct List *temp = head;
head = head->next;
free(temp);
} return 0;
}

更多语言版本

不同语言实现设计模式:https://github.com/microwind/design-pattern

【迭代器设计模式详解】C/Java/JS/Go/Python/TS不同语言实现的更多相关文章

  1. [ 转载 ] Java开发中的23种设计模式详解(转)

    Java开发中的23种设计模式详解(转)   设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...

  2. Java温故而知新(5)设计模式详解(23种)

    一.设计模式的理解 刚开始“不懂”为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“简单”就是一把钥匙开一把锁的模式,目 ...

  3. [转载]Java迭代器(iterator详解以及和for循环的区别)

    Java迭代器(iterator详解以及和for循环的区别) 觉得有用的话,欢迎一起讨论相互学习~[Follow] 转载自 https://blog.csdn.net/Jae_Wang/article ...

  4. JAVA设计模式简介及六种常见设计模式详解

    一.什么是设计模式                                                                                           ...

  5. android java 设计模式详解 Demo

    android java 设计模式详解 最近看了一篇设计模式的文章,深得体会,在此基础我将每种设计模式的案例都写成Demo的形式,方便读者研究学习, 首先先将文章分享给大家: 设计模式(Design ...

  6. Javascript设计模式详解

    Javascript常用的设计模式详解 阅读目录 一:理解工厂模式 二:理解单体模式 三:理解模块模式 四:理解代理模式 五:理解职责链模式 六:命令模式的理解: 七:模板方法模式 八:理解javas ...

  7. Javascript常用的设计模式详解

    Javascript常用的设计模式详解 阅读目录 一:理解工厂模式 二:理解单体模式 三:理解模块模式 四:理解代理模式 五:理解职责链模式 六:命令模式的理解: 七:模板方法模式 八:理解javas ...

  8. javascript设计模式详解之策略模式

    接上篇命令模式来继续看下js设计模式中另一种常用的模式,策略模式.策略模式也是js开发中常用的一种实例,不要被这么略显深邃的名字给迷惑了.接下来我们慢慢看一下. 一.基本概念与使用场景: 基本概念:定 ...

  9. iOS中MVC等设计模式详解

    iOS中MVC等设计模式详解 在iOS编程,利用设计模式可以大大提高你的开发效率,虽然在编写代码之初你需要花费较大时间把各种业务逻辑封装起来.(事实证明这是值得的!) 模型-视图-控制器(MVC)设计 ...

  10. javascript设计模式详解之命令模式

    每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某 ...

随机推荐

  1. CentOS7 进入修复模式的办法

    有时候配置Centos文件修改错误会导致系统无法登录,可以通过修复模式进行单用户运行模式,进行修复. 具体操作如下: 1.重启服务器,在选择内核界面使用上下箭头移动 2.选择内核并按"e&q ...

  2. [Cisco] Policy Based Routing

    在某些情況下,會希望指定特定的來源及目的走特定的出口,卻又不是全部的網段都希望套用,這時就可以透過PBR來達成這個需求. 如以下拓樸 1.1.1.0/24的網路往5.5.5.0的封包需要指定e0/1當 ...

  3. golang学习路线

    一.golang基础 李文周的博客:https://www.liwenzhou.com/ 视频教程:https://link.juejin.cn/?target=https%3A%2F%2Fwww.b ...

  4. 借助5G智能网关实现无人化智慧农业应用

    发展智慧农业是新时代的必由之路.依托5G+物联网技术赋能农业生产,能够实现更少的人员需求,更大面积的综合土地管理,更实时精细的生产环境监测,更智能的生产自主管控.5G技术正以其广连接.低时延的优势,助 ...

  5. 10.Java中Map的entrySet() 详解以及用法

    一.Map.entry是什么? Map是java中的接口,Map.Entry是Map的一个内部接口. 此接口为泛型,定义为Entry<K,V>.它表示Map中的一个实体(一个key-val ...

  6. Git在使用过程中遇到的一些问题

    git默认对文件中的大小写不敏感. 方案1: 通过配置git来达到识别文件大小写的问题.命令如下: git config core.ignorcecase false 缺点:每个仓库都需要修改. 方案 ...

  7. ArcEngine(平板电脑墨迹错误代码。多次调用 RtpEnabled (异常来自 HRESULT:0x80040239))问题未有效解决

    测试数据库中的要素无法执行ITopologicOperater接口下的方法,错误如图 暂记,错误未解决 tip: 1.随便移动一个节点 也不报错/ 2.手动按照他的节点画一个也不报错 3.bufer参 ...

  8. swiper常见问题、动态加载数据问题

    swiper加载静态文件是没有问题的 swiper加载动态文件需要在请求后再加载这个函数 参考链接:  https://blog.csdn.net/webzrh/article/details/781 ...

  9. java并发编程实践-线程安全性

    线程是CPU资源调度的基本单位,如果一个程序中只有一个线程,则最多只能在一个处理器上运行,如果电脑/服务器是双处理器系统,则单线程的程序只能使用一半的CPU资源,所以,多线程是提高处理器资源利用率的重 ...

  10. 《MySQL是怎样运行的》第一章小结