基本需求:

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

传统方案:

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

基本介绍:

  • 迭代器模式(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. 十八般武艺玩转GaussDB(DWS)性能调优(三):好味道表定义

    摘要:表结构设计是数据库建模的一个关键环节,表定义好坏直接决定了集群的有效容量以及业务查询性能,本文从产品架构.功能实现以及业务特征的角度阐述在GaussDB(DWS)的中表定义时需要关注的一些关键因 ...

  2. Django前后端安全验证

    会话技术 关注公众号"轻松学编程"了解更多. 1.Cookie 客户端会话技术(数据存储在客户端) 以key-value的形式进行存储 cookie的操作都是通过Response来 ...

  3. LWJGL3的内存管理,第一篇,基础知识

    LWJGL3的内存管理,第一篇,基础知识 为了讨论LWJGL在内存分配方面的设计,我将会分为数篇随笔分开介绍,本篇将主要介绍一些大方向的问题和一些必备的知识. 何为"绑定(binding)& ...

  4. 【CHOJ】磁力块

    题意描述 磁力块 在平面内分布着 \(N\) 个磁力块,同时你的手上也有一块. 你一开始站在给定的坐标上,当磁力块之间满足互相吸引的条件时就可以吸引. 当你拿到新的磁石时你就可以用它来吸引更多的石头, ...

  5. C语言100题集合004-统计各个年龄阶段的人数

    系列文章<C语言经典100例>持续创作中,欢迎大家的关注和支持. 喜欢的同学记得点赞.转发.收藏哦- 后续C语言经典100例将会以pdf和代码的形式发放到公众号 欢迎关注:计算广告生态 即 ...

  6. 基于 .NET 的 FluentValidation 数据验证

    学习地址:官方文档,更多更详细的内容可以看官方文档. FluentValidation 是一个基于 .NET 开发的验证框架,开源免费,而且优雅,支持链式操作,易于理解,功能完善,还是可与 MVC5. ...

  7. 动态JavaWeb工程的架构问题

    B/S 网络应用的分层 前端(表示层) 后端( 业务逻辑层, 数据库访问层 ) 分层的目的->分模块->解耦 1,表示层---和用户直接交互 html,js,css, servlet 2, ...

  8. Python_列表相减(判断长度后长的减短的)

    #定义一个方法,可进行列表相减 class V(object): def __init__(self,*value): self.value=value def __sub__(self,other) ...

  9. Kubernetes 入门与安装部署

    一.简介 参考:Kubernetes 官方文档.Kubernetes中文社区 | 中文文档 Kubernetes 是一个可移植的.可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自 ...

  10. Web安全常见漏洞修复建议

    转载地址:https://security.pingan.com/blog/17.html SQL注入 在服务器端要对所有的输入数据验证有效性. 在处理输入之前,验证所有客户端提供的数据,包括所有的参 ...