基本需求:

  • 展示一个学校的结构,比如一个学校下面有多个学院,学院下面有多个系,对其节点主要是遍历,与组合模式略有不同

传统方案:

  • 学校<-学院<-系 依次继承
  • 这种方式,在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系,因此这种方案,不能很好实现的遍历的操作,并且他们之间也没有继承关系,使用继承并不合适

基本介绍:

  • 迭代器模式(Iterator)是常用的设计模式,属于行为型模式,这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示

  • 如果我们的集合元素是用不同的方式实现的,有数组,还有java的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决

  • 迭代器模式提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构

  • 把在元素之间游走的责任交给迭代器,而不是聚合对象

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

  • UML类图(原理)

    • 说明
      • Iterator:迭代器接口,直接使用JDK提供的即可提供,含有hasNext, next, remove
      • ConcreteIterator:具体的迭代器类,进行元素迭代,其内部元素的以不同的方式进行存储,例如数组、list等
      • Aggregate:一个统一的聚合接口,将客户端和具体聚合解耦,进行元素的存储
      • ConcreteAggreage:具体的聚合持有对象集合,并提供一个方法,返回一个迭代器,该迭代器可以正确遍历集合,和ConcreteIterator一一对应
      • Element:集合内部所存储的元素
      • 实际情况中一般将ConcreteIterator作为内部类放入ConcreteAggreage类中,直接省去了元素集合elementes的传递
  • UML类图(案例)

    • 说明
      • OutputImpl:用于输出信息的辅助类
  • 代码实现

    • 迭代器类不作为持有迭代集合类的内部类

      • @Data
        @AllArgsConstructor
        public class Department { // 迭代器内部元素 private String name; private String description; }
      • public class ComputerCollegeIterator implements Iterator {
        
           // 计算机学院迭代器,元素使用数组存储 一般会将迭代器实现类作为需要迭代对象的内部类
        
           private Department[] departments;
        
           // 当前位置指针
        private int index = 0; public ComputerCollegeIterator(Department[] departments) {
        this.departments = departments;
        } // 判断是否有下一个元素
        @Override
        public boolean hasNext() {
        return !(this.index >= this.departments.length);
        } // 返回下一个元素
        @Override
        public Department next() {
        return this.departments[this.index++];
        } @Override
        public void remove() {
        // 移除方法空实现
        } }
      • public class InfoCollegeIterator implements Iterator {
        
           // 信息工程学院迭代器,元素使用List集合存储 一般会将迭代器实现类作为需要迭代对象的内部类
        
           private List<Department> departments;
        
           // 当前位置指针
        private int index = 0; public InfoCollegeIterator(List<Department> departments) {
        this.departments = departments;
        } // 判断是否有下一个元素
        @Override
        public boolean hasNext() {
        return !(this.index >= this.departments.size());
        } // 返回下一个元素
        @Override
        public Department next() {
        return this.departments.get(this.index++);
        } @Override
        public void remove() {
        // 移除方法空实现
        } }
      • public interface College {
        
           // 学院接口
        
           // 获取学院名称
        String getName(); // 给学院内部添加系
        void addDepartment(String name, String description); // 获取该学院所对应的迭代器
        Iterator createIterator(); } // 实现类一 计算机学院
        class ComputerCollege implements College { // 存储内部元素的集合,用于获取迭代器
        private Department[] departments; // 当前元素位置指针
        private int index; public ComputerCollege() {
        this.departments = new Department[5];
        this.index = 0;
        addDepartment("Java专业", "Java专业 ");
        addDepartment("PHP专业", "PHP专业 ");
        addDepartment("大数据专业", "大数据专业");
        } @Override
        public String getName() {
        return "计算机学院";
        } @Override
        public void addDepartment(String name, String description) {
        Department department = new Department(name, description);
        this.departments[this.index++] = department;
        } @Override
        public Iterator createIterator() {
        return new ComputerCollegeIterator(this.departments);
        } } // 实现类二 信息工程学院
        class InfoCollege implements College { // 存储内部元素的集合,用于获取迭代器
        private List<Department> departments; public InfoCollege() {
        this.departments = new ArrayList<Department>();
        addDepartment("信息安全专业", "信息安全专业");
        addDepartment("网络安全专业", "网络安全专业");
        addDepartment("服务器安全专业", "服务器安全专业");
        } @Override
        public String getName() {
        return "信息工程学院";
        } @Override
        public void addDepartment(String name, String description) {
        this.departments.add(new Department(name, description));
        } @Override
        public Iterator createIterator() {
        return new InfoCollegeIterator(this.departments);
        } }
      • public class OutputImpl {
        
           // 输出迭代器元素内部的实现类
        
           private List<College> colleges;
        
           public OutputImpl(List<College> colleges) {
        this.colleges = colleges;
        } public void printCollege() {
        // 获取List集合内部的迭代器
        Iterator<College> iterator = colleges.iterator();
        while (iterator.hasNext()) {
        College college = iterator.next();
        System.out.println("======" + college.getName() + "======");
        // 获取学院内部系的迭代器进行迭代输出 而不需要知道元素再内部以什么形式的集合存在,统一了遍历方式
        printDepartment(college.createIterator());
        }
        } private void printDepartment(Iterator iterator) {
        while (iterator.hasNext()) {
        Department department = (Department) iterator.next();
        if (null != department) {
        System.out.println(department.getName() + "-----" + department.getDescription());
        }
        }
        } }
      • public class Client {
        public static void main(String[] args) {
        // 创建学院的集合
        List<College> colleges = new ArrayList<College>();
        colleges.add(new ComputerCollege());
        colleges.add(new InfoCollege());
        // 创建输出类 并迭代输出学院及其下面的系
        OutputImpl output = new OutputImpl(colleges);
        output.printCollege();
        }
        }
    • 迭代器类作为持有迭代集合类的内部类

      • // 实现类一 计算机学院
        public class ComputerCollege implements College { // 存储内部元素的集合,用于获取迭代器
        private Department[] departments; // 当前元素位置指针
        private int index; public ComputerCollege() {
        this.departments = new Department[5];
        this.index = 0;
        addDepartment("Java专业", "Java专业 ");
        addDepartment("PHP专业", "PHP专业 ");
        addDepartment("大数据专业", "大数据专业");
        } @Override
        public String getName() {
        return "计算机学院";
        } @Override
        public void addDepartment(String name, String description) {
        Department department = new Department(name, description);
        this.departments[this.index++] = department;
        } @Override
        public Iterator createIterator() {
        return new ComputerCollegeIterator();
        } // 迭代器类作为持有迭代集合类的内部类
        private class ComputerCollegeIterator implements Iterator { // 计算机学院迭代器,元素使用数组存储 一般会将迭代器实现类作为需要迭代对象的内部类 // 当前位置指针
        private int index = 0; // 判断是否有下一个元素 直接使用上层类的元素集合即可
        @Override
        public boolean hasNext() {
        return !(this.index >= ComputerCollege.this.departments.length);
        } // 返回下一个元素 直接使用上层类的元素集合即可
        @Override
        public Department next() {
        return ComputerCollege.this.departments[this.index++];
        } @Override
        public void remove() {
        // 移除方法空实现
        } } }
      • // 实现类二 信息工程学院
        public class InfoCollege implements College { // 存储内部元素的集合,用于获取迭代器
        private List<Department> departments; public InfoCollege() {
        this.departments = new ArrayList<Department>();
        addDepartment("信息安全专业", "信息安全专业");
        addDepartment("网络安全专业", "网络安全专业");
        addDepartment("服务器安全专业", "服务器安全专业");
        } @Override
        public String getName() {
        return "信息工程学院";
        } @Override
        public void addDepartment(String name, String description) {
        this.departments.add(new Department(name, description));
        } @Override
        public Iterator createIterator() {
        return new InfoCollegeIterator();
        } // 迭代器类作为持有迭代集合类的内部类
        private class InfoCollegeIterator implements Iterator { // 信息工程学院迭代器,元素使用List集合存储 一般会将迭代器实现类作为需要迭代对象的内部类 // 当前位置指针
        private int index = 0; // 判断是否有下一个元素 直接使用上层类的元素集合即可
        @Override
        public boolean hasNext() {
        return !(this.index >= InfoCollege.this.departments.size());
        } // 返回下一个元素 直接使用上层类的元素集合即可
        @Override
        public Department next() {
        return InfoCollege.this.departments.get(this.index++);
        } @Override
        public void remove() {
        // 移除方法空实现
        } } }

jdk源码:

  • 在jdk的ArrayList源码中就使用到了迭代器模式

  • UML类图

    • 说明

      • List就是充当了聚合接口,含有一个iterator()方法,返回一个迭代器对象

      • ArrayList是实现聚合接口List的子类,实现了iterator()

      • ArrayList内部的elementData属性就是存放元素的集合,是一个数组Object[]

      • Itr充当具体实现迭代器Iterator的类,作为ArrayList内部类

      • Iterator接口JDk提供

      • public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
        {
        // 存储元素的集合
        transient Object[] elementData; // 实现获取迭代器方法
        public Iterator<E> iterator() {
        return new Itr();
        } /**
        * An optimized version of AbstractList.Itr
        */
        // 作为ArrayList内部类 实现迭代器Iterator
        private class Itr implements Iterator<E> {
        ......
        }
        }

注意事项:

  • 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了
  • 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成
  • 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器
  • 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式
  • 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类

16.java设计模式之迭代器模式的更多相关文章

  1. 折腾Java设计模式之迭代器模式

    迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its ...

  2. 简单的了解下Java设计模式:迭代器模式(转载)

    迭代器模式定义 迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. Java 开发过程中遍历是常用的.如下边程序: for(int i =0 ; ...

  3. java设计模式之迭代器模式

    一.迭代器模式简介 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露内部的表示.把游走的任务放在迭代器上,而不是 ...

  4. Python进阶:设计模式之迭代器模式

    在软件开发领域中,人们经常会用到这一个概念——“设计模式”(design pattern),它是一种针对软件设计的共性问题而提出的解决方案.在一本圣经级的书籍<设计模式:可复用面向对象软件的基础 ...

  5. 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)

    设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...

  6. Java设计模式之builder模式

    Java设计模式之builder模式 今天学mybatis的时候,知道了SQLSessionFactory使用的是builder模式来生成的.再次整理一下什么是builder模式以及应用场景. 1. ...

  7. 实践GoF的设计模式:迭代器模式

    摘要:迭代器模式主要用在访问对象集合的场景,能够向客户端隐藏集合的实现细节. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:迭代器模式>,作者:元闰子. 简介 有时会遇到这 ...

  8. Java设计模式——装饰者模式

    JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...

  9. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

随机推荐

  1. 如何做可靠的分布式锁,Redlock真的可行么

    本文是对 Martin Kleppmann 的文章 How to do distributed locking 部分内容的翻译和总结,上次写 Redlock 的原因就是看到了 Martin 的这篇文章 ...

  2. Java_Math类和Random类

    Math类 java.lang.Math提供了一系列静态方法用于科学计算, 其方法的参数和返回值类型一般都为double型, 如果需要更加强大的数学运算能力计算高等数学中的相关内容, 可使用apach ...

  3. 内网渗透 day7-linux信息收集

    linux信息搜集 目录 1. linux信息搜集 2. nmap漏洞复现 3. msf linux模块反弹shell 1. linux信息搜集 id 查看当前用户的权限和所在的管理组 python ...

  4. WEB安全问题

    WEB安全问题我没太多经验,但是这块内容还是很重要,所以必须要了解学习一下. 简单总结了一下,分成以下5类, 1.DDOS,瘫痪式攻击,解决方法是记录异常请求的ip地址,主动拒绝或者将攻击ip添加到防 ...

  5. margin的讲究

    什么元素允许有margin值,无论块状元素还是行内元素都可以,只是各有限制. 先说行内元素,这个是不允许有上下 外边距的, 再说块状元素,上下左右外边距都允许  但是相邻元素的外边距会合并,要注意的是 ...

  6. [MIT6.006] 12. Square Roots, Newton's Method 平方根,牛顿法

    首先让我们回顾下上节课讲的,用牛顿法计算√2的内容: 简单来说,牛顿法从x0=1不断向后计算逼近√2的值,而刚开始计算的精度是1,随着牛顿法的逼近(共log2d个循环),就能使得√2逼近值的精度达到d ...

  7. 牛客网-声网2020校招-通用C++笔试题-2020.9.3

    1. 操作系统中两个进程争夺同一个资源会发生什么情况? 答:不一定死锁 解析:产生死锁的四个必要条件为 (1)互斥条件:一个资源每次只能被一个进程使用. (2)不可剥夺条件:进程已获得的资源,在未使用 ...

  8. Fiddler的一系列学习瞎记3

    Http: 不安全.可以很容易被拦截,或者其他的嗅探工具发现.怎么样做到安全?起码一下两点: 1.浏览器和we服务器之间的内容应该只有浏览器和web服务器能看到通信内容. 2.Http请求和Http的 ...

  9. Docker与Ceph的分与合

    前言 docker是一个管理工具,在操作系统之上提供了一个新的独立轻环境,好处是本地提供了一个基础镜像,然后基于镜像再运行环境,也可以把环境重新打包为镜像,管理起来类似于git,感觉非常的方便,并且能 ...

  10. 利用移动硬盘安装windows7系统

    首先把win7系统镜像的iso文件解压到移动硬盘中 将移动硬盘设置为活动分区 设置活动分区的方法 Diskpart程序实现U盘安装WIN7的方法: 将Win7安装盘中的所有文件拷贝到硬盘文件夹中,我们 ...