首页 > 编程语言 >【迭代器设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

【迭代器设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

时间:2023-04-17 12:24:13浏览次数:52  
标签:Java struct 迭代 Python Iterator iter next 设计模式 objectList

简介

迭代器模式(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

标签:Java,struct,迭代,Python,Iterator,iter,next,设计模式,objectList
From: https://www.cnblogs.com/letjs/p/17325457.html

相关文章

  • Python 深度学习架构实用指南:第三、四、五部分
    原文:Hands-OnDeepLearningArchitectureswithPython协议:CCBY-NC-SA4.0译者:飞龙本文来自【ApacheCN深度学习译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。不要担心自己的形象,只关心如何实现目标。——《原则》,生活原则2.3.c第3节:序列建模在本节中,我们将学习......
  • python学习之-加密字体反扒
    #coding=utf-8'''#获取实习僧招聘信息#(https://www.shixiseng.com/interns?page=2&type=intern&keyword=%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98&area=&months=&days=°ree=&official=&enterprise=&salary=-0&publishTime=......
  • 技术老鸟告诉你Python为什么能一跃成为世界排名第一的语言
    本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注"慕课网"!作者:大周|慕课网讲师一、前言本文将结合个人经历为各位同学客观的分析是否有学习Python的必要、Python适合谁学、为什么要学,希望能够给看到此文章的同学一点建议,树立学习目标,让学习有结果。读完后,相信你一......
  • 记录selenium,python自动化测试中的chromedriver.exe地址和打开后自动关闭浏览器问题
    selenium的官方地址为:https://selenium-python.readthedocs.io/index.html镜像地址:https://npmmirror.com/#导入webdriverfromseleniumimportwebdriverfromselenium.webdriver.common.byimportBy#调用键盘按键操作时需要引入的Keys包fromselenium.webdriver.common.k......
  • [python] Python枚举模块enum总结
    枚举是一种数据类型,在编程中用于表示一组相关的常量。枚举中的每个常量都有一个名称和一个对应的值,可以用于增强代码的可读性和可维护性。在Python中,枚举是由enum模块提供的,而不是Python提供专用的枚举语法。关于enum模块介绍见:enum。如需详细了解Python的enum模块,参见文章:Python......
  • python代码:基于强化学习的智能电网的动态定价方法
    python代码:基于强化学习的智能电网的动态定价方法摘要:提出了一种考虑服务提供商(SP)利润和用户(CUs)成本的分级电力市场中能量管理的动态定价DR算法。使用强化学习(RL)描述分层决策框架,将动态定价问题描述为离散有限马尔可夫决策过程(MDP),并采用Q学习求解该决策问题。使用RL,S......
  • 设计模式二:工厂模式之简单工厂
    一、简介1.1什么是简单工厂模式在软件开发中,我们经常需要根据不同的需求创建不同的对象或者实例,为了实现这一目的,我们通常会采用工厂模式。工厂模式是一种创建型模式,它提供了一种创建对象的最佳方式。工厂模式分为简单工厂、工厂方法和抽象工厂三种,本文将重点介绍简单工厂模式。简......
  • python报错:divide by zero encountered in log
    原因:数字太小的原因,溢出,计算过程中出现-inf,再做其他运算,结果还是-inf。当概率很小时,取对数后结果趋于负无穷大解决:改变浮点数的精度参考:(51条消息)RuntimeWarning:dividebyzeroencounteredinlog错误解决_旅途中的宽~的博客-CSDN博客......
  • 关于Python爬虫使用技巧
    首先,Python是一种非常流行的编程语言,拥有广泛的应用领域,例如数据分析、人工智能、Web开发等。如果您是初学者,可以开始学习基础的语法和概念,例如变量、数据类型、循环、函数等等。许多在线资源可以提供学习资料。其次,Python拥有大量的第三方库和框架,可以帮助您提高开发效率并处理......
  • java json 四个格式
    java官方<dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20220320</version></dependency>codeJSONObjectjsonObject=newJSONObject();jsonObject.put("secretKey......