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


    简介

    迭代器模式(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 
    #include 
    
    // 简单版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

  • 相关阅读:
    wondows10用Electron打包threejs的项目记录
    在Springboot HandlerInterceptor中获取GET和POST请求参数
    vue3初体验-基于vue3+ant design封装公共弹框
    http相应状态码,重定向和转发区别,文件下载流对应格式
    小程序分包的详细流程
    OS-process
    线性代数矩阵相关知识回顾
    docker for windows 转移存储位置
    OpenResty学习笔记03:再探WAF
    【深入理解C++】局部变量及初始化
  • 原文地址:https://www.cnblogs.com/letjs/p/17325457.html