迭代器模式的Java实现

迭代器模式简述

迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。

迭代器模式属于行为型模式。

介绍

意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示,内部可以是数组或者链表等。

主要解决:不同的方式来遍历整个整合对象,实现迭代器接口的具有统一的遍历方式,而不用追究其本质。

何时使用:遍历一个聚合对象。

如何解决:把在元素之间游走的责任交给迭代器,而不是聚合对象。

关键代码:定义接口:hasNext, next。

应用实例:JAVA 中的 iterator。C++ STL中的Iterator

优点:

  • 它支持以不同的方式遍历一个聚合对象。
  • 迭代器简化了聚合类。
  • 在同一个聚合上可以有多个遍历。
  • 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点:

  • 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类。
  • 类的个数成对增加,这在一定程度上增加了系统的复杂性。

使用场景:

  • 访问一个聚合对象的内容而无须暴露它的内部表示。
  • 需要为聚合对象提供多种遍历方式。
  • 为遍历不同的聚合结构提供一个统一的接口。

注意事项:迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。

基本案例:

  • 正向遍历迭代器实现(本文实现这个案例)
  • 逆向遍历迭代器实现

迭代器设计模式划分:

  • AggregateContainer 获取Iterator实例的接口定义
  • ConcreteContainer实现AggregateContainer
  • ConcreteIterator实现Iterator
  • ConcreteIterator与ConcreteContainer配对,所以将ConcreteIterator作为ConcreteContainer的内部类

实现

场景:实现正向遍历迭代器

  • 提供一种可以遍历对象集合的方式,又称为:游标cursor模式
  • 聚合对象:存储数据,这里我在代码中定义成Container接口,用于获取迭代器对象
  • 迭代器:遍历数据

步骤1:创建抽象了迭代器类,用于规划有哪些操作

package com.ly.iterator;

/**
 * liyang 2020-08-21
 * 自定义的迭代器接口
 * 定义了一些常用的接口函数
 */

public interface MyIterator {
    //迭代器初始值,如果有的地方需要,移动到-1位置,方便某些操作的统一性
    void moveToMinusOne();

    boolean moveToFirst();     //移动游标到第一个位置
    boolean next();            //移动游标到下一个位置
    boolean hasNext();         //判断游标是否有下一个位置

    boolean isFirst();         //判断当前游标是否是第一个位置
    boolean isLast();          //判断当前游标是否是最后一个位置

    Object getCurrentObject(); //获取当前游标所指向的对象
}

步骤2:创建抽象的容器

package com.ly.iterator;

/**
 * liyang 2020-08-21
 * 抽象的聚合容器类,主要用于获取迭哪类代器
 * 抽象的聚合容器被具体容器实现
 */

public interface AggregateContainer {
    MyIterator getMyIterator();
}

步骤3:创建具体的容器类实现抽象的聚合容器类,由于迭代器的实现是为了对该具体容器的使用和操作,所以具体迭代器类在具体容器类中以内部类的方式存在,并且实现抽象迭代器接口

package com.ly.iterator;

import java.util.ArrayList;
import java.util.List;

/**
 * liyang 2020-08-21
 * 具体容器类实现抽象的聚合容器
 * 具体的迭代器类实现抽象的迭代器,作为具体容器类的内部类
 * 这里的具体的迭代器依托于list容器实现
 * 上述get、set方法使用IDEA统一生成,有的可能在测试中未使用
 */

public class ConcreteContainer implements AggregateContainer {

    private List<Object> list = new ArrayList<>();

    public List<Object> getList() {
        return list;
    }

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

    void addObject(Object object) {
        list.add(object);
    }

    void removeObject(Object object) {
        list.remove(object);
    }

    @Override
    public MyIterator getMyIterator() {
        return new ConcreteIterator();
    }

    //使用内部类的定义方式,让ConcreteIterator服务于ConcreteContainer
    private class ConcreteIterator implements MyIterator {

        private int cursor = -1; //用于记录遍历时的位置

        @Override
        public void moveToMinusOne() {
            cursor = -1;
        }

        @Override
        public boolean moveToFirst() {
            if(list.size() >= 1) {
                cursor = 0;
                return true;
            }
            return false;

        }

        @Override
        public boolean next() {
            if(hasNext()) {
                cursor++;
                return true;
            }
            return false;
        }

        @Override
        public boolean hasNext() {
            return cursor + 1 < list.size();
        }

        @Override
        public boolean isFirst() {
            return cursor == 0;
        }

        @Override
        public boolean isLast() {
            return cursor == list.size() - 1;
        }

        @Override
        public Object getCurrentObject() {
            if(cursor >= 0 && cursor < list.size()) return list.get(cursor);
            else return null;
        }
    }

}

步骤4:客户端测试

package com.ly.iterator;

/**
 * liyang 2020-08-21
 * 客户端测试
 */

public class Client {
    public static void main(String[] args) {
        ConcreteContainer carNameContainer = new ConcreteContainer();
        //测试添加
        carNameContainer.addObject("byd");
        carNameContainer.addObject("bmw");
        carNameContainer.addObject("benz");
        carNameContainer.addObject("audi");
        //测试删除
        carNameContainer.removeObject("bmw");
        //获取迭代器,测试isFist()与isLast()
        MyIterator myIterator = carNameContainer.getMyIterator();
        System.out.println("Is first ? : " + myIterator.isFirst());
        System.out.println("Move to first : " + myIterator.moveToFirst());
        System.out.println("Is first now ? : " + myIterator.isFirst());
        //遍历相关函数测试
        System.out.println("--遍历方法1--");
        if(myIterator.moveToFirst()) {
            do {
                System.out.println(myIterator.getCurrentObject());
            } while(myIterator.next()); //next()内部先判断是否有next,即hasNext(),有则移动到下一个位置并返回真
        }
        System.out.println("Is last ? : " + myIterator.isLast());

        System.out.println("--遍历方法2--");
        if(myIterator.moveToFirst()) {
            System.out.println(myIterator.getCurrentObject());
            while(myIterator.next()) {
                System.out.println(myIterator.getCurrentObject());
            }
        }
        System.out.println("Is last ? : " + myIterator.isLast());

        System.out.println("--遍历方法3--");
        myIterator.moveToMinusOne();
        while(myIterator.next()) {
            System.out.println(myIterator.getCurrentObject());
        }
        System.out.println("Is last ? : " + myIterator.isLast());
    }
}

结果

Is first ? : false
Move to first : true
Is first now ? : true
--遍历方法1--
byd
benz
audi
Is last ? : true
--遍历方法2--
byd
benz
audi
Is last ? : true
--遍历方法3--
byd
benz
audi
Is last ? : true

Process finished with exit code 0

参考资料:

https://www.runoob.com/design-pattern/iterator-pattern.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值