• 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专业", "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> {
                ......
             }
          }
          
          

    注意事项

    • 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了
    • 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成
    • 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器
    • 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式
    • 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类
  • 相关阅读:
    this 指向 及 调用方式
    页面布局上 左 右底部
    Thread Safety线程安全
    sql查删更
    LinuxMysql命令操作数据库
    excel链接sharepoint 用于 Excel 的 Microsoft Power Query
    W7无法更新
    发票点数计算
    sharepoint OWA问题解决
    zend studio 做前端推荐安装的插件
  • 原文地址:https://www.cnblogs.com/xiaokantianse/p/14074725.html
Copyright © 2020-2023  润新知