前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图解设计模式:动动手玩转迭代器模式

图解设计模式:动动手玩转迭代器模式

作者头像
冷环渊
发布2022-12-15 14:32:31
3190
发布2022-12-15 14:32:31
举报

前言

☀️☀️点开就是缘分认识一下,我是小冷。是一个兴趣驱动自学练习两年半的的Java工程师。 一位十分喜欢将知识分享出来的Java博主⭐️⭐️⭐️,擅长使用Java技术开发web项目和工具 文章内容丰富:覆盖大部分java必学技术栈,前端,计算机基础,容器等方面的文章 如果你也对Java感兴趣,关注小冷吧,一起探索Java技术的生态与进步,一起讨论Java技术的使用与学习 ✏️高质量技术专栏专栏链接: 微服务数据结构netty单点登录SSMSpringCloudAlibaba等 ⏩当前专栏设计模式系列专栏代码地址: 代码地址

动动手玩转迭代器模式(iterator)

​ 在Java语言中当我们需要查看数组的时候,我们最常见的方法就是使用循环预语句来遍历数组。

以for循环举例子

    for (int i = 0; i < arr.length; i++) {
      System.out.println(arr[i]);
    }

在for中 i++ 代表每次循环让 i 增加 来做到数组可以从前到后的遍历元素

将 i 抽象出来 形成通用化的模式 就是设计中的 迭代器模式

ps: 迭代器模式常用于 数组和集合遍历中

示例理解

我们用下图的书架来实现一个迭代器模式的示例 :

​ 示例程序的功能内容很简单就是我们将书架中书本的内容按照放入到顺序显示出来

image-20221214190242171
image-20221214190242171
类与接口
image-20221214190414674
image-20221214190414674
接口

迭代器接口 , 想要遍历某一个类这个类值具有两个条件

  • 实现了Aggregate接口 表示这个类可以被迭代器遍历
  • 有实现了Iterator 接口的适合本类型的迭代器器
public interface Iterator {

  public abstract boolean hasNext();

  public abstract Object next();
}
public interface  Aggregate {
    public abstract Iterator iterator();
}

Book 放 在书架上的书本类型

public class Book {

  private String Name;

  public Book(String name) {
    this.Name = name;
  }

  public String getName() {
    return  Name;
  }

}

书架

  • 放入书本
  • 查看书本(根据书本的index 来查找)
  • 获得书本数量
public class BookShelf implements Aggregate {

  private Book[] books;
  private int last = 0;

  public BookShelf(int maxsize) {
   this.books = new Book[maxsize];
  }

  public void appendBook(Book book) {
    this.books[last] = book;
    last++;
  }

  public int getLength() {
    return last;
  }

  public Iterator iterator(){
    return new BookShelfIterator(this);
  }

  public Book getBookAt(int index) {
      return books[index];
  }

用于查找书本的迭代器

  • 实现迭代器接口
  • 实现对书架的遍历
  • 实现拿出功能
public class BookShelfIterator implements Iterator {
  private BookShelf bookShelf;
  private int index;

  public BookShelfIterator(BookShelf bookShelf) {
    this.bookShelf = bookShelf;
  }

  @Override
  public boolean hasNext() {
    if(index<bookShelf.getLength()){
      return true;
    }else {
      return false;
    }
  }

  @Override
  public Object next() {
    Book bookAt = bookShelf.getBookAt(index);
    index++;
    return bookAt;
  }
}
示例测试

测试示例,简易的实现了对抽象循环i 来完成迭代书架展示书本内容

public class Test {

  public static void main(String[] args) {
    BookShelf bookShelf = new BookShelf(4);
    bookShelf.appendBook(new Book("A"));
    bookShelf.appendBook(new Book("B"));
    bookShelf.appendBook(new Book("C"));
    bookShelf.appendBook(new Book("D"));
    Iterator iterator = bookShelf.iterator();
    while (iterator.hasNext()){
      Book next = (Book) iterator.next();
      System.out.println(next.getName());
    }
  }
}
image-20221214191254711
image-20221214191254711

迭代器中的角色

​ 在实现了简单的示例程序中 我们来回看一下迭代器中出现了哪几个角色

  • 迭代器 iterator 由它来定义一个迭代器规范
  • 具体的迭代器 Concretelterator :bookshlefiterator 基于迭代器规范实现了对书架的遍历
  • 集合 Aggrrgate 由它来定义一个创建迭代器的规范
  • 具体的集合 ConcreteAggregate :bookshelf基于Aggrrgate 规范实现了让这个类可以创建自己的迭代器

迭代器模式的类图

拓展思路

为什么要用

​ Q : 为什么一定要考虑引入迭代器这样相对麻烦的设计模式呢?

​ Q : 如果只是数组 直接用循环来迭代不就可以吗 为什么要在集合之外引入迭代器这个角色呢?

​ A : 一个重要的理由 进入了迭代器之后 可以将遍历与实现分离开

代码片段

while (iterator.hasNext()){
  Book next = (Book) iterator.next();
  System.out.println(next.getName());
}

​ 这里知识使用率迭代器的 hasnext 和 next 方法,并没有调用 booskshelf 的方法 也就是说这里循环并不依赖 booskshelf 。

​ 那么如果假设 现在开发 booskshelf 的人员决定放弃数组来管理书本 而是选择用Java中的其他容器比如list vector取而代之呢,会如何? 不管 booskshelf 如何变化 只要 booskshelf 方法的 iterator 能正确的返回 iterator示例 即使不对上面的循环代码做任何的改动,代码也可以正常工作

​ 在没有迭代器模式的时候 人们总是用着实现好的类来直接操作 而不是定义一些抽象的规则 这也导致了代码复用性差,他们总是想用具体的类来解决所有的问题

Aggregate 与 iterator 对应

​ 我们在示例中 把booskshelfiterator定义为booskshelf 这个类的迭代器实现,也就是说 booskshelfiterator知道booskshelf 是如何实现的,也正是因为这个实现,我们可以获取下一本书的getBookAt方法。

​ 也就是说如果 booskshelf 发生改变 ,getBookAt这个方法也需要改变,改变的同时,我们也需要去修改

booskshelfiterator,正如Aggregate和iterator对应一样,实现的集合和迭代器也需要是对应的

拓展示例(改为arraylist来存放数据)

​ 只需要将书架类的数据操作方式稍作修改就可以实现替换存储结构,不需要去修改其他代码,操作代码的方式就变化了

public class BookShelf implements Aggregate {

  private ArrayList<Book> books;

  public BookShelf() {
   this.books = new ArrayList<>();
  }

  public void appendBook(Book book) {
    this.books.add(book);
  }

  public int getLength() {
    return books.size();
  }

  public Iterator iterator(){
    return new BookShelfIterator(this);
  }

  public Book getBookAt(int index) {
      return books.get(index);
  }

}

测试代码

  public static void main(String[] args) {
    BookShelf bookShelf = new BookShelf();
    bookShelf.appendBook(new Book("A"));
    bookShelf.appendBook(new Book("B"));
    bookShelf.appendBook(new Book("C"));
    bookShelf.appendBook(new Book("D"));
    Iterator iterator = bookShelf.iterator();
    while (iterator.hasNext()){
      Book next = (Book) iterator.next();
      System.out.println(next.getName());
    }
  }
image-20221214191254711
image-20221214191254711

如果还想再通用一些可以使用泛型来将数据类型也变为可以传入的,过于简单所以提供一下思路即可

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-12-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 动动手玩转迭代器模式(iterator)
    • 示例理解
      • 类与接口
      • 示例测试
    • 迭代器中的角色
      • 拓展思路
        • 为什么要用
        • Aggregate 与 iterator 对应
      • 拓展示例(改为arraylist来存放数据)
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档