• 详解设计模式:迭代器模式


    迭代器模式(Iterator Pattern)也被称为游标模式(Cursor Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。是一种最简单也最常见的设计模式。

    迭代器模式 可以让用户透过特定的接口巡访容器中的每一个元素而不用了解底层的实现。

    本篇文章内容包括:关于迭代器模式、观察者模式 Demo、模版方法模式的应用(ArrayList/Iterator 中的迭代器模式)



    一、关于迭代器模式

    1、关于迭代器模式

    迭代器模式(Iterator Pattern)也被称为游标模式(Cursor Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。是一种最简单也最常见的设计模式。

    迭代器模式 可以让用户透过特定的接口巡访容器中的每一个元素而不用了解底层的实现。

    迭代器模式 提供一种方法顺序访问一个聚合(指一组对象的组合结构,如:Java中的集合、数组等)对象中各个元素,而又不需暴露该对象的内部表示。迭代器模式的本质:控制访问聚合对象中的元素。其设计意图:无须暴露聚合对象的内部实现,就能够访问到聚合对象中的各个元素。

    2、关于迭代器模式的构成

    迭代器模式主要包含以下 4 种角色:

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

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

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

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

    3、关于迭代器模式的XML

    image-20221203180812127

    4、关于迭代器模式的适用场景
    • 内容保密 : 访问 集合对象 的内容 , 无需暴露内部表示 ;
    • 统一接口 : 为遍历 不同的 集合结构 , 提供统一接口。
    5、关于迭代器模式的优缺点

    迭代器模式优点

    • 分离了集合对象的遍历行为;
    • 抽象出了迭代器负责集合对象的遍历 , 可以让外部的代码透明的访问集合内部的数据 ;

    迭代器模式缺点

    • 类的个数成对增加;
    • 迭代器模式,将存储数据 , 遍历数据两个职责拆分 ;
    • 如果新添加一个 集合类 , 需要增加该 集合类 对应的 迭代器类 , 类的个数成对增加 , 在一定程度上 , 增加了系统复杂性 ;

    二、观察者模式 Demo

    1、Demo 设计

    定义一个可以存储学生对象的容器对象,将遍历该容器的功能交由迭代器实现。

    Demo 类图如下:

    在这里插入图片描述
    2、Demo 实现

    # Student 元素类

    public class Student {
    
        private String name;
    
        private String number;
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", number='" + number + '\'' +
                    '}';
        }
    
        /**
         * 建造者类构造函数
         *
         * @param builder Builder
         */
        private Student(Builder builder) {
            name = builder.name;
            number = builder.number;
        }
    
        /**
         * 建造者类
         */
        public static final class Builder {
    
            private String name;
    
            private String number;
    
            public Builder() {
            }
    
            public Builder name(String val) {
                name = val;
                return this;
            }
    
            public Builder number(String val) {
                number = val;
                return this;
            }
    
            public Student build() {
                return new Student(this);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    # StudentAggregate 抽象聚合(Aggregate)角色

    public interface StudentAggregate {
        
        /**
         * 添加元素
         * @param student Student
         */
        void addStudent(Student student);
    
        /**
         * 删除元素
         * @param student Student
         */
        void removeStudent(Student student);
    
        /**
         * 获取迭代器对象
         * @return StudentIterator
         */
        StudentIterator getStudentIterator();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    # StudentAggregateImpl 具体聚合(ConcreteAggregate)角色

    import java.util.ArrayList;
    import java.util.List;
    
    public class StudentAggregateImpl implements StudentAggregate {
    
        /**
         * 学生列表
         */
        private final List<Student> list = new ArrayList<Student>();
    
        @Override
        public void addStudent(Student student) {
            this.list.add(student);
        }
    
        @Override
        public void removeStudent(Student student) {
            this.list.remove(student);
        }
    
        @Override
        public StudentIterator getStudentIterator() {
            return new StudentIteratorImpl(list);
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    # StudentIterator 抽象迭代器(Iterator)角色

    public interface StudentIterator {
    
        /**
         * 判断是否还有下一个元素
         * @return boolean
         */
        boolean hasNext();
    
        /**
         * 获取下一个元素
         * @return Student
         */
        Student next();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    # StudentIteratorImpl 具体迭代器(Concretelterator)角色

    import java.util.List;
    
    public class StudentIteratorImpl implements StudentIterator {
    
        private final List<Student> list;
        private int position = 0;
    
        public StudentIteratorImpl(List<Student> list) {
            this.list = list;
        }
    
        @Override
        public boolean hasNext() {
            return position < list.size();
        }
    
        @Override
        public Student next() {
            Student currentStudent = list.get(position);
            position ++;
            return currentStudent;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    3、Demo 测试
    public class Client {
    
        public static void main(String[] args) {
            
            // 抽象聚合类-StudentAggregate 具体聚合类-StudentAggregateImpl
            StudentAggregate studentAggregate = new StudentAggregateImpl();
            // 建造者模式构造元素
            studentAggregate.addStudent(new Student.Builder().name("小明").number("1001").build());
            studentAggregate.addStudent(new Student.Builder().name("小红").number("1002").build());
            // 通过 具体聚合类 获取 具体迭代器
            StudentIterator iterator = studentAggregate.getStudentIterator();
            
            // 迭代器遍历
            while (iterator.hasNext()){
                System.out.println(iterator.next().toString());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    三、模版方法模式的应用(ArrayList/Iterator 中的迭代器模式)

    Java 代码中关于 List 的迭代器使用:

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class IteratorDemo {
    
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("AA");
            list.add("BB");
            list.add("CC");
            
            // list.iterator() 方法返回的肯定是 Iterator 接口的子实现类对象
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    其中,List-抽象聚合类、ArrayList-具体的聚合类、Iterator-抽象迭代器、list.iterator() 返回的是实现了 Iterator 接口的具体迭代器对象。

    # ArrayList 的源码对于迭代器部分的实现:

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
        
        public Iterator<E> iterator() {
            return new ArrayList.Itr();
        }
        
        
        private class Itr implements Iterator<E> {
          	// 下一个要返回元素的索引
            int cursor;       
          	// 上一个返回元素的索引
            int lastRet = -1; 
            int expectedModCount = modCount;
    
            Itr() {}
    		
            //判断是否还有元素
            public boolean hasNext() {
                return cursor != size;
            }
    
            //获取下一个元素
            public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }
            ...
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    可以看到:在 iterator 方法中返回了一个实例化的 Iterator 对象。Itr 是一个内部类,它实现了 Iterator 接口并重写了其中的抽象方法。

    // List 集成自 Collection
    public interface List<E> extends Collection<E>
    
    // Collection 继承自 Iterable
    public interface Collection<E> extends Iterable<E>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Ps:当我们在使用 Java 开发的时候,想使用迭代器模式的话,只要让我们自己定义的容器类实现 java.util.Iterable 并实现其中的 iterator() 方法使其返回一个 java.util.Iterator 的实现类就可以了。

  • 相关阅读:
    3ds Max渲染太慢?创意云“一键云渲染”提升3ds Max渲染体验
    循环购模式:美业的新机遇和新挑战
    万物皆可集成系列:低代码对接阿里物流API实现快递跟踪
    鹰潭高通量测序建设细节概述
    《CTF攻防世界web题》之茶壶我爱你(2)
    2023李宏毅机器学习HW05样例代码中文注释版
    C++ Reference: Standard C++ Library reference: C Library: cwchar: vswprintf
    LuBase 低代码开发框架介绍 - 可私有化部署
    MySQL——函数和流程控制
    面试高频手撕算法 - 背包问题2
  • 原文地址:https://blog.csdn.net/weixin_45187434/article/details/128164451