Java设计模式之迭代器模式

本文介绍设计模式中的迭代器模式,首先通俗的解释迭代器模式的基本概念和对应的四个角色,并根据四个角色举一个典型的实例,为了加强知识的连贯性,我们以Jdk源码集合中使用迭代器模式的应用进一步说明,最后说明迭代器模式的应用场景和优缺点。

读者可以拉取完整代码本地学习,实现代码均测试通过上传到码云,本地源码下载。

一、概念理解

迭代器模式官方解释就是提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。何为聚合对象呢?最典型的就是集合类。

大白话也就是,集合中的数据是私有的,集合中不应该提供直接遍历的方法,要定义一个新的对象用于访问这个集合。

既然是一个专门用来遍历的对象,一个被遍历的聚合对象,很显然至少有两个对象,迭代器对象、聚合对象,由于遵循面向接口编程的原则,迭代器对象和聚合对象应该抽象出来接口,那自然而然就是应该有四个角色:

抽象聚合(InterfaceAggregate)角色:定义存储、添加、删除聚合元素以及创建迭代器对象的接口。

具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。

抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、next() 等方法。

具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

基于四个角色我们举一个典型案例。

二、案例实现

应该是有四个类

抽象聚合角色,用于定义增删改查元素的统一规范接口,和创建迭代器对象的方法

具体聚合角色,实现抽象聚合角色方法

抽象迭代器角色,定义遍历元素的统一规范接口

具体迭代器,实现抽象迭代器角色的方法。

抽象聚合角色:

/**
 * 抽象聚合角色
 * @author tcy
 * @Date 13-09-2022
 */
public interface InterfaceAggregate {
    /**
     * 增加对象
     * @param obj 对象
     */
    void add(Object obj);

    /**
     * 移除对象
     * @param obj 对象
     */
    void remove(Object obj);

    /**
     * 调用迭代器
     * @return 迭代器
     */
    Iterator getIterator();
}

具体聚合角色:

/**
 * 具体聚合角色
 * @author tcy
 * @Date 13-09-2022
 */
public class ConcreteAggregate implements InterfaceAggregate{
    private List<Object> list = new ArrayList<>();
    @Override
    public void add(Object obj) {
        list.add(obj);
    }

    @Override
    public void remove(Object obj) {
        list.remove(obj);
    }

    @Override
    public Iterator getIterator() {
        return new Concretelterator(list);
    }
}

抽象迭代器角色:

/**
 * 抽象迭代器
 * @author tcy
 * @Date 13-09-2022
 */
public interface Iterator<E> {

    /**
     * 删除对象
     * @return 对象
     */
    Object remove();

    /**
     * 调用下一个对象
     * @return 对象
     */
    E next();

    /**
     * 迭代器中是否还有下一个对象
     * @return
     */
    boolean hasNext();

    /**
     * 遍历迭代器中剩余的对象
     * @param action
     */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }

}

具体迭代器角色:

/**
 * 具体迭代器角色
 * @author tcy
 * @Date 13-09-2022
 */
public class Concretelterator implements Iterator{
    private List<Object> list = null;
    private int index = -1;

    public Concretelterator(List<Object> list) {
        this.list = list;
    }

    @Override
    public Object remove() {
        index = list.size();
        Object obj = list.get(index);
        list.remove(obj);
        return obj;
    }

    @Override
    public Object next() {
        Object obj = null;
        if (this.hasNext()) {
            obj = list.get(++index);
        }
        return obj;
    }

    @Override
    public boolean hasNext() {
        if (index < list.size() - 1) {
            return true;
        } else {
            return false;
        }
    }
}

客户端调用:

/**
 * @author tcy
 * @Date 13-09-2022
 */
public class Client {

    public static void main(String[] args) {
        ConcreteAggregate concreteAggregate=new ConcreteAggregate();
        concreteAggregate.add("老王");
        concreteAggregate.add("小王");
        concreteAggregate.add("小张");

        System.out.println("Aggregate聚合对象有:");

        Iterator iterator=concreteAggregate.getIterator();

        while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next.toString());
        }
        //遍历剩下的角色
        iterator.forEachRemaining(ele -> System.out.println(ele));

    }

}

迭代器实现逻辑比较清晰,理解起来难度也不大,了解了该设计模式,趁热打铁看迭代器模式在源码中的应用。

三、源码应用

迭代器模式在Jdk中的集合类中有着广泛的应用,我们以ArrayList作为典型。

在ArrayList实现迭代器时,同样是有四个角色。

List抽象聚合类;

ArrayList具体聚合角色;

Iterator抽象迭代器;

ArrayList内部类Itr是具体迭代器;

我们可以看到ArrayList是把具体聚合角色和具体迭代器都写在一个类中,Itr作为具体迭代对象是以内部类的形式。

ArrayList其实和我们案例中的方法长的很像,只不过ArrayList中定义了更多的方法,而且ArrayList还有一个内部类ListItr。

其实是迭代器的增强版,在继承Itr的基础之上实现ListIterator接口。

Iterator迭代器除了,hasNext()、next()、remove()方法以外,还有一个特别的forEachRemaining()方法,我们重点说下forEachRemaining()方法,该方法代表的意思是遍历剩下的集合。

比如我们已经调用了该集合中的第一个元素,那么遍历时候就会自动忽略第一个元素,遍历剩下的元素。

我们写一个测试方法看效果:

public class Client {

    public static void main(String[] args) {

        // jdk ArrayList迭代器
        //创建一个元素类型为Integer的集合
        Collection<String> collection =  new ArrayList<>();

            //向集合中添加元素
            collection.add("老王");
            collection.add("小王");
            collection.add("小张");

        //获取该集合的迭代器
        java.util.Iterator<String> iteratorJdk= collection.iterator();
        System.out.println("Arraylist聚合对象有:");
        //调用迭代器的经过集合实现的抽象方法遍历集合元素
        while(iteratorJdk.hasNext())
        {
            System.out.println(iteratorJdk.next());
        }
        //调用forEachRemaining()方法遍历集合元素
        iteratorJdk.forEachRemaining(ele -> System.out.println(ele));

    }

}

Arraylist聚合对象有:
老王
小王
小张

正常情况下,会打印两次集合对象中的信息,实际上只打印了一次,正是由于next调用过的元素,forEachRemaining不会再调。

看到这,想必你对迭代器已经有了初步的了解,当在遍历元素时,除了使用for循环遍历元素以外,提供了另外一种方式遍历元素。

案例很好理解,源码中的应用也看得懂,但是实际开发中迭代器对象什么时候用呢?想必大部分人并不是很清晰。

接着看迭代器对象的应用场景和优缺点,看从中能不能找到答案。

四、总结

当一个对象是一个聚合对象且需要对外提供遍历方法时,可以使用迭代器模式,也即实际业务中定义的有聚合对象,里面存放了我们需要的业务数据,为了让业务数据的职责更清晰,我们就可以将编辑的方法提取出来,另外定义一个迭代器对象用于遍历数据。

迭代器方式提供了不同的方式遍历聚合对象,增加新的聚合类和迭代器类都是比较方便的,Java集合类中庞大的家族采用迭代器模式就是基于这种优点。

迭代器模式有设计模式的通用缺点——系统复杂性,迭代器模式将数据存储和数据遍历分开,增加了类的个数。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • Java 数据结构算法Collection接口迭代器示例详解

    目录 Java合集框架 Collection接口 迭代器 Java合集框架 数据结构是以某种形式将数据组织在一起的合集(collection).数据结构不仅存储数据,还支持访问和处理数据的操作 在面向对象的思想里,一种数据结构也被认为是一个容器(container)或者容器对象(container object),它是一个能存储其他对象的对象,这里的其他对象常被称为数据或者元素 定义一种数据结构从实质上讲就是定义一个类.数据结构类应该使用数据域存储数据,并提供方法支持查找.插入和删除等操作 Ja

  • 深入理解Java设计模式之迭代器模式

    目录 一.什么是迭代器模式 二.迭代器模式的结构 三.迭代器模式的使用场景 四.迭代器模式的优缺点 优点: 缺点: 五.迭代器模式的实现 抽象聚合类 迭代器抽象类 具体聚合类 具体迭代器类 客户端调用 六.NET中迭代器模式的应用 七.总结 一.什么是迭代器模式 迭代器模式是针对集合对象而生的,对于集合对象而言,肯定会涉及到对集合的添加和删除操作,同时也肯定支持遍历集合元素的操作,我们此时可以把遍历操作放在集合对象中,但这样的话,集合对象既承担太多的责任了,面向对象设计原则中有一条就是单一职责原

  • Java迭代器遍历list的方法及代码分析

    Java迭代器遍历list的方法是什么?动力节点小编来告诉大家.迭代器可用于遍历ArrayList.如果ArrayList中有更多元素,则hasNext()方法返回true,否则返回false.next()方法返回ArrayList中的下一个元素,如果没有下一个元素,则引发异常NoSuchElementException. 演示该程序的程序如下. import java.util.ArrayList; import java.util.Iterator; public class Demo {

  • Java迭代器与Collection接口超详细讲解

    目录 关于迭代器你都知道什么? 什么是迭代器? 迭代器的4个API 如何使用迭代器? Collection集合接口知多少? 为什么不使用数组而是集合? Collection接口的API都有什么? AbstractCollection类知多少? 关于迭代器你都知道什么? 什么是迭代器?   所谓迭代的意思就是交换替代,迭代器并不是一种数据结构或者集合,而是可以过迭代器中的方法逐个访问集合中的每个元素的一种方法.提到迭代器最重要的就是Iterator接口,所有想要使用迭代器迭代的结构都需要实现或者继

  • Java Iterator迭代器与foreach循环代码解析

    目录 一. Iterator迭代器接口 1. 使用 Iterator 接口遍历集合元素 2. Iterator接口的方法 3. 迭代器的执行原理 3.1 代码演示 3.2 代码执行过程解析 4. Iterator接口remove()方法 4.1 代码演示 4.2 注意 5. 代码演示 二.foreach 循环 1. 概述 2. 语法解析 3. 代码演示 4. 易错题 一. Iterator迭代器接口 1. 使用 Iterator 接口遍历集合元素 Iterator对象称为迭代器(设计模式的一种)

  • Java深入分析Iterator迭代器与foreach循环的使用

    目录 一.Iterator迭代器接口 1. 使用Iterator接口遍历集合元素 2. Iterator接口的方法 3. 迭代器的执行原理 3.1 代码演示 3.2 代码执行过程解析 4. Iterator接口remove()方法 4.1 代码演示 4.2 注意 5. 代码演示 二.foreach 循环 1. 概述 2. 语法解析 3. 代码演示 4. 易错题 一.Iterator迭代器接口 1. 使用Iterator接口遍历集合元素 Iterator对象称为迭代器(设计模式的一种),主要用于遍

  • Java中BigDecimal,DateFormatter 和迭代器的"陷阱"

    前言: 使用 IDEA 创建一个 Maven 项目 calculate-date-traps 并导入 Junit 依赖. <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> 在进行计费时使

  • Java设计模式之迭代器模式_动力节点Java学院整理

    定义:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节. 类型:行为类模式 类图: 如果要问Java中使用最多的一种模式,答案不是单例模式,也不是工厂模式,更不是策略模式,而是迭代器模式,先来看一段代码吧: public static void print(Collection coll){ Iterator it = coll.iterator(); while(it.hasNext()){ String str = (String)it.next(); System.out

  • Java设计模式之迭代器模式

    本文介绍设计模式中的迭代器模式,首先通俗的解释迭代器模式的基本概念和对应的四个角色,并根据四个角色举一个典型的实例,为了加强知识的连贯性,我们以Jdk源码集合中使用迭代器模式的应用进一步说明,最后说明迭代器模式的应用场景和优缺点. 读者可以拉取完整代码本地学习,实现代码均测试通过上传到码云,本地源码下载. 一.概念理解 迭代器模式官方解释就是提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示.何为聚合对象呢?最典型的就是集合类. 大白话也就是,集合中的数据是私有的,集合中不

  • Android编程设计模式之迭代器模式详解

    本文实例讲述了Android编程设计模式之迭代器模式.分享给大家供大家参考,具体如下: 一.介绍 迭代器模式(Iterator Pattern)又称为游标(Cursor)模式,是行为型设计模式之一.迭代器模式算是一个比较古老的设计模式,其源于对容器的访问,比如Java中的List.Map.数组等,我们知道对容器对象的访问必然会涉及遍历算法,我们可以将遍历的方法封装在容器中,或者不提供遍历方法.如果我们将遍历的方法封装到容器中,那么对于容器类来说就承担了过多的功能,容器类不仅要维护自身内部的数据元

  • PHP设计模式之迭代器模式的使用

    一说到这个模式,就不得不提循环语句.在<大话设计模式>中,作者说道这个模式现在的学习意义更大于实际意义,这是为什么呢?当然就是被foreach这货给整得.任何语言都有这种类似的语法可以方便快捷的对数组.对象进行遍历,从而让迭代器模式从高高在上的23大设计模式中的明星慢慢成为了路人.特别是我们这门PHP语言,PHP的强大之处就在于对于数组的灵活操作,本身就是hashmap的结构,自然会有各种方便的数组操作语法,而foreach也是我们最常用的语句,甚至比for还常用. Gof类图及解释 GoF定

  • Java设计模式之备忘录模式_动力节点Java学院

    定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样就可以将该对象恢复到原先保存的状态 类型:行为类 类图: 我们在编程的时候,经常需要保存对象的中间状态,当需要的时候,可以恢复到这个状态.比如,我们使用Eclipse进行编程时,假如编写失误(例如不小心误删除了几行代码),我们希望返回删除前的状态,便可以使用Ctrl+Z来进行返回.这时我们便可以使用备忘录模式来实现. 备忘录模式的结构 发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和

  • JAVA设计模式之建造者模式原理与用法详解

    本文实例讲述了JAVA设计模式之建造者模式定义与用法.分享给大家供大家参考,具体如下: 建造者模式:将复杂对象的构造与它的实现相分离,让相同的构建过程可以创建不同的对象. 适用场合: 复杂对象的算法应该独立于该对象的组成部分或当构造过程允许被构造不同的对象时. 组成角色: 1 创建者(Builder)接口:为创建一个对象的对应部件所指定抽象接口. 2 具体创建者(ConcreteBuilder):实现Builder的接口以构造对象的各个部件. 3 具体创建者管理对象(Director):使用Bu

  • java设计模式之工厂模式实例详解

    本文实例讲述了java设计模式之工厂模式.分享给大家供大家参考,具体如下: 工厂模式(factory) 涉及到4个角色:抽象工厂类角色,具体工厂类角色,抽象产品类角色和具体产品类角色. 抽象工厂类角色使用接口或者父类来描述工厂的行为, 具体工厂类角色负责创建某一类型的产品对象. 抽象产品类可以使用接口或者父类来描述产品对象的行为特征. 具体产品类就是某一具体的对象. 工厂模式不同于静态工厂模式的地方: 工厂模式在工厂类也实现了多态,而不仅仅是在产品对象上实现多态. 它可以应对不同类型的产品对应一

  • Java设计模式之桥接模式实例详解

    本文实例讲述了Java设计模式之桥接模式.分享给大家供大家参考,具体如下: 概念: 桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化. 桥接模式将继承关系转换为关联关系,从而降低了类与类之间的耦合,减少了代码编写量. 什么情况下会用桥接模式? 简单的说就是我们在抽象对象的特征时,对象的特征属性又很抽象,不得不把属性再次抽象. 否则的话,具体子类的数量将会成几何增长,而且不易扩展.没办法维护现有代码. 举例,我们在抽象手机这二个对象时,它的几个属性,如

  • Java设计模式之建造者模式实例详解

    本文实例讲述了Java设计模式之建造者模式.分享给大家供大家参考,具体如下: 建造者模式(builder)可以将部件和其组装过程分开.一步一步创建一个复杂的对象. 用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节. 什么情况下会用到建造者模式? 个人理解,当我们创建的对象在创建时需要逻辑的时候. 比如,一个简单的pojo对象,我们想要创建,直接就可以new出来,没有什么逻辑. 当有一个复杂的对象,你想要创建它时,它的各个属性之间是有逻辑关系的. 一个属性赋值取值依赖于

随机推荐