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

基本需求:

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

传统方案:

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

基本介绍:

  • 迭代器模式(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专业",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("信息安全专业",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> {
              ......
           }
        }
        
        

注意事项:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结