聊聊Java设计模式-迭代器模式

简介: 迭代器(Iterator)模式,也叫做游标(Cursor)模式。我们知道,在Java 容器中,为了提高容器遍历的方便性,我们利用迭代器把遍历逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合容器的内部结构。

迭代器(Iterator)模式,也叫做游标(Cursor)模式。我们知道,在Java 容器中,为了提高容器遍历的方便性,我们利用迭代器把遍历逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合容器的内部结构。

一、迭代器模式介绍

迭代器模式也就是提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。它是一种行为型模式,下面就来看看迭代器模式的结构:

1.1 迭代器模式的结构

迭代器模式的结构很简单,就是将聚合对象中的遍历行为分离,并抽象成迭代器类来实现:

image-20220406161104154

  • Aggregate:抽象聚合接口,定义对聚合对象的一些操作和创建迭代器对象的接口
  • Iterator:抽象迭代器接口,定义访问和遍历聚合元素的接口
  • Aggregate1:具体聚合实现,实现抽象聚合接口,返回一个具体迭代器实例对象
  • Iterator1:具体迭代器实现,实现抽象迭代器接口中所定义的方法

1.2 迭代器模式的实现

根据上面的类图,可以实现如下代码:

/**
 * @description: 抽象聚合接口
 * @author: wjw
 * @date: 2022/4/6
 */
public interface Aggregate {
   
   
    /**
     * 增加对象
     * @param obj 对象
     */
    void add(Object obj);

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

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

/**
 * @description: 具体迭代器类
 * @author: wjw
 * @date: 2022/4/6
 */
public class Aggregate1 implements Aggregate{
   
   

    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 Iterator1(list);
    }
}
/**
 * @description: 抽象迭代器
 * @author: wjw
 * @date: 2022/4/6
 */
public interface Iterator {
   
   

    /**
     * 调用第一个对象
     * @return 对象
     */
    Object first();

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

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

}

/**
 * @description: 具体迭代器类
 * @author: wjw
 * @date: 2022/4/6
 */
public class Iterator1 implements Iterator{
   
   

    private List<Object> list = null;
    private int index = -1;

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

    @Override
    public Object first() {
   
   
        index = 0;
        Object obj = list.get(index);
        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;
        }
    }
}
/**
 * @description: 客户端类
 * @author: wjw
 * @date: 2022/4/6
 */
public class Client {
   
   
    public static void main(String[] args) {
   
   
        Aggregate1 aggregate1 = new Aggregate1();
        aggregate1.add("A");
        aggregate1.add("B");
        aggregate1.add("C");
        System.out.println("聚合对象有:");
        Iterator iterator = aggregate1.getIterator();
        while (iterator.hasNext()) {
   
   
            Object obj = iterator.next();
            System.out.println(obj.toString());
        }
        Object first = iterator.first();
        System.out.println("第一个聚合对象是:" + first.toString());
    }
}

客户端测试场结果为:

聚合对象有:
A
B
C
第一个聚合对象是:A

二、迭代器模式的应用场景

2.1 Java 集合容器

Java 集合容器中的使用就是容器中的迭代器了,以ArrayList为例,ArrayList是继承Collection的:

image-20220406193326506

我们发现ArrayList类里面实现迭代器接口的内部类:

image-20220406192935330

其中Itr实现IteratorListItr继承Itr并实现ListIteratorListIteratorIterator功能的扩展。所以实际上ArrayList是抽象聚合和抽象迭代器两者的具体实现,可以画出大致结构图如下:

image-20220406194540279

举个使用ArrayList的例子:

public static void main(String[] args) {
   
   
    ArrayList<String> list = new ArrayList<>();
    list.add("A");
    list.add("B");
    list.add("C");
    Iterator<String> iterator = list.iterator();
    System.out.println("ArrayList中的聚合对象为:");
    while (iterator.hasNext()) {
   
   
        String next = iterator.next();
        System.out.println(next);
    }
}

输出结果:

ArrayList中的聚合对象为:
A
B
C

在日常业务的开发中,迭代器模式使用的场景并不多,下面就来看看关于迭代器的实战

三、迭代器模式实战

在本案例中模拟迭代遍历输出公司中树形结构的组织结构关系中雇员列表:

公司案例

利用迭代器模式实现的结构如下:

image-20220406200217207

上面结构是以Java容器中迭代器模式基础构建的,左边是迭代器的定义,右边是实现的迭代器功能。具体代码结构图如下:

├─src
│  ├─main
│  │  ├─java
│  │  │  ├─group
│  │  │  │      Employee.java
│  │  │  │      GroupStructure.java
│  │  │  │      Link.java
│  │  │  │
│  │  │  └─lang
│  │  │          Collection.java
│  │  │          Iterable.java
│  │  │          Iterator.java
│  │  │
│  │  └─resources
│  └─test
│      └─java
│              ApiTest.java

对于lang包下是迭代器实现部分,具体代码如下:

/**
 * @description: 可迭代接口定义
 * @author: wjw
 * @date: 2022/4/6
 */
public interface Iterator<E> {
   
   

    boolean hasNext();

    E next();
}
/**
 * @description:
 * @author: wjw
 * @date: 2022/4/6
 */
public interface Iterable<E> {
   
   

    Iterator<E> iterator();
}
/**
 * @description: 集合功能接口
 * @author: wjw
 * @date: 2022/4/6
 */
public interface Collection<E, L> extends Iterable<E> {
   
   

    boolean add(E e);

    boolean remove(E e);

    boolean addLink(String key, L l);

    boolean removeLink(String key);

    /**
     * 继承Iterable接口的方法
     * @return Iterator
     */
    @Override
    Iterator<E> iterator();
}

group包下是组织结构以及聚类对象及其实现,具体代码如下所示:

/**
 * @description: 雇员类
 * @author: wjw
 * @date: 2022/4/6
 */
public class Employee {
   
   

    private String uId;
    private String name;
    private String desc;

    public Employee(String uId, String name, String desc) {
   
   
        this.uId = uId;
        this.name = name;
        this.desc = desc;
    }

    public String getuId() {
   
   
        return uId;
    }

    public void setuId(String uId) {
   
   
        this.uId = uId;
    }

    public String getName() {
   
   
        return name;
    }

    public void setName(String name) {
   
   
        this.name = name;
    }

    public String getDesc() {
   
   
        return desc;
    }

    public void setDesc(String desc) {
   
   
        this.desc = desc;
    }
}
/**
 * @description: 树节点链路
 * @author: wjw
 * @date: 2022/4/6
 */
public class Link {
   
   

    private String fromId;
    private String toId;

    public Link(String fromId, String toId) {
   
   
        this.fromId = fromId;
        this.toId = toId;
    }

    public String getFromId() {
   
   
        return fromId;
    }

    public void setFromId(String fromId) {
   
   
        this.fromId = fromId;
    }

    public String getToId() {
   
   
        return toId;
    }

    public void setToId(String toId) {
   
   
        this.toId = toId;
    }
}
/**
 * @description: 迭代器功能实现
 * @author: wjw
 * @date: 2022/4/6
 */
public class GroupStructure implements Collection<Employee, Link> {
   
   

    /**组织ID*/
    private String groupId;

    /**组织名称*/
    private String groupName;

    /**雇员列表*/
    private Map<String, Employee> employeeMap = new ConcurrentHashMap<>();

    /**组织架构关系*/
    private Map<String, List<Link>> linkMap = new ConcurrentHashMap<>();

    /**反向关系链*/
    private Map<String, String> invertedMap = new ConcurrentHashMap<>();

    public GroupStructure(String groupId, String groupName) {
   
   
        this.groupId = groupId;
        this.groupName = groupName;
    }

    @Override
    public boolean add(Employee employee) {
   
   
        return null != employeeMap.put(employee.getuId(), employee);
    }

    @Override
    public boolean remove(Employee employee) {
   
   
        return null != employeeMap.remove(employee.getuId());
    }

    @Override
    public boolean addLink(String key, Link link) {
   
   
        invertedMap.put(link.getToId(), link.getFromId());
        if (linkMap.containsKey(key)) {
   
   
            return linkMap.get(key).add(link);
        } else {
   
   
            List<Link> links = new LinkedList<>();
            links.add(link);
            linkMap.put(key, links);
            return true;
        }
    }

    @Override
    public boolean removeLink(String key) {
   
   
        return null != linkMap.remove(key);
    }

    @Override
    public Iterator<Employee> iterator() {
   
   
        return new Iterator<Employee>() {
   
   

            HashMap<String, Integer> keyMap = new HashMap<>();
            int totalIdx = 0;
            //雇员ID,From
            private String fromId = groupId;
            //雇员ID,To
            private String toId = groupId;

            @Override
            public boolean hasNext() {
   
   
                return totalIdx < employeeMap.size();
            }

            @Override
            public Employee next() {
   
   
                List<Link> links = linkMap.get(toId);
                int cursorIdx = getCursorIdx(toId);

                //同级扫描
                if (null == links) {
   
   
                    cursorIdx = getCursorIdx(fromId);
                    links = linkMap.get(fromId);
                }
                //上级节点扫描
                while (cursorIdx > links.size() - 1) {
   
   
                    fromId = invertedMap.get(fromId);
                    cursorIdx = getCursorIdx(fromId);
                    links = linkMap.get(fromId);
                }

                //获取节点
                Link link = links.get(cursorIdx);
                toId = link.getToId();
                fromId = link.getFromId();
                totalIdx++;

                //返回最终结果
                return employeeMap.get(link.getToId());
            }

            //给每个层级定义宽度遍历进度
            public int getCursorIdx(String key) {
   
   
                int idx = 0;
                if (keyMap.containsKey(key)) {
   
   
                    idx = keyMap.get(key);
                    keyMap.put(key, ++idx);
                } else {
   
   
                    keyMap.put(key, idx);
                }
                return idx;
            }
        };
    }
}

最后是测试类及其结果:

/**
 * @description: 单元测试类
 * @author: wjw
 * @date: 2022/4/6
 */
public class ApiTest {
   
   

    private Logger logger = LoggerFactory.getLogger(ApiTest.class);

    @Test
    public void test_iterator() {
   
   
        GroupStructure groupStructure = new GroupStructure("1", "ethan");
        groupStructure.add(new Employee("2", "花花", "二级部门"));
        groupStructure.add(new Employee("3", "豆包", "二级部门"));
        groupStructure.add(new Employee("4", "蹦蹦", "三级部门"));
        groupStructure.add(new Employee("5", "大烧", "三级部门"));
        groupStructure.add(new Employee("6", "虎哥", "四级部门"));
        groupStructure.add(new Employee("7", "玲姐", "四级部门"));
        groupStructure.add(new Employee("8", "秋雅", "四级部门"));

        //添加节点链接
        groupStructure.addLink("1", new Link("1", "2"));
        groupStructure.addLink("1", new Link("1", "3"));

        groupStructure.addLink("2", new Link("2", "4"));
        groupStructure.addLink("2", new Link("2", "5"));

        groupStructure.addLink("5", new Link("5", "6"));
        groupStructure.addLink("5", new Link("5", "7"));
        groupStructure.addLink("5", new Link("5", "8"));

        Iterator<Employee> iterator = groupStructure.iterator();
        while (iterator.hasNext()) {
   
   
            Employee employee = iterator.next();
            logger.info("{},雇员 Id: {} Name: {}", employee.getDesc(), employee.getuId(), employee.getName());
        }
    }
}
21:50:11.087 [main] INFO  ApiTest - 二级部门,雇员 Id: 2 Name: 花花
21:50:11.089 [main] INFO  ApiTest - 三级部门,雇员 Id: 4 Name: 蹦蹦
21:50:11.089 [main] INFO  ApiTest - 三级部门,雇员 Id: 5 Name: 大烧
21:50:11.089 [main] INFO  ApiTest - 四级部门,雇员 Id: 6 Name: 虎哥
21:50:11.089 [main] INFO  ApiTest - 四级部门,雇员 Id: 7 Name: 玲姐
21:50:11.089 [main] INFO  ApiTest - 四级部门,雇员 Id: 8 Name: 秋雅
21:50:11.089 [main] INFO  ApiTest - 二级部门,雇员 Id: 3 Name: 豆包

参考资料

《重学Java设计模式》

http://c.biancheng.net/view/1395.html

目录
相关文章
|
21天前
|
设计模式 Java 开发者
设计模式揭秘:Java世界的七大奇迹
【4月更文挑战第7天】探索Java设计模式:单例、工厂方法、抽象工厂、建造者、原型、适配器和观察者,助你构建健壮、灵活的软件系统。了解这些模式如何提升代码复用、可维护性,以及在特定场景下的应用,如资源管理、接口兼容和事件监听。掌握设计模式,但也需根据实际情况权衡,打造高效、优雅的软件解决方案。
|
22天前
|
设计模式 存储 Java
23种设计模式,享元模式的概念优缺点以及JAVA代码举例
【4月更文挑战第6天】享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享技术有效地支持大量细粒度对象的重用。这个模式在处理大量对象时非常有用,特别是当这些对象中的许多实例实际上可以共享相同的状态时,从而可以减少内存占用,提高程序效率
35 4
|
21天前
|
设计模式 监控 Java
设计模式 - 观察者模式(Observer):Java中的战术与策略
【4月更文挑战第7天】观察者模式是构建可维护、可扩展系统的关键,它在Java中通过`Observable`和`Observer`实现对象间一对多的依赖关系,常用于事件处理、数据绑定和同步。该模式支持事件驱动架构、数据同步和实时系统,但需注意避免循环依赖、控制通知粒度,并关注性能和内存泄漏问题。通过明确角色、使用抽象和管理观察者注册,可最大化其效果。
|
1天前
|
设计模式 消息中间件 Java
Java 设计模式:探索发布-订阅模式的原理与应用
【4月更文挑战第27天】发布-订阅模式是一种消息传递范式,被广泛用于构建松散耦合的系统。在 Java 中,这种模式允许多个对象监听和响应感兴趣的事件。
8 2
|
1天前
|
设计模式 算法 Java
Java 设计模式:探索策略模式的概念和实战应用
【4月更文挑战第27天】策略模式是一种行为设计模式,它允许在运行时选择算法的行为。在 Java 中,策略模式通过定义一系列的算法,并将每一个算法封装起来,并使它们可以互换,这样算法的变化不会影响到使用算法的客户。
6 1
|
1天前
|
设计模式 安全 Java
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
|
4天前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
|
4天前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
|
4天前
|
设计模式 存储 JavaScript
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
|
4天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式