迭代器模式

1 输出院系结构的需求

在之前将的组合模式中提到了打印院系结构的需求,当时是采用组合模式实现的,现在我们用迭代器模式来实现一下。

2 迭代器模式介绍

迭代器模式(Iterator Pattern)也是一种常用的设计模式,属于行为性模式。如果我们的集合元素是用不同的方式实现的,有数组、集合、链表等,当客户端想要遍历这些集合元素的时候就要使用多种遍历方式,而且会暴露元素的内部结构。迭代器模式提供了一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合的底层表示。
角色分析:
1)Iterator:迭代器接口,包含hasNext、next、remove方法。
2)ConcreteIterator:迭代器实现类。
3)Aggregate:一个统一的聚合接口,将客户端和具体的元素解耦。
4)ConcreteAggregate:具体的聚合持有对象集合,并且提供一个返回迭代器的方法,该迭代器可以正确遍历集合。
5)Client:客户端类,通过Aggregate和Iterator进行遍历。


迭代器模式的类图

3 迭代器模式实现需求

首先由一个Department实体类:

public class Department {
    private String name;
    private String desc;

    public Department(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

数学学院的迭代器实现类:

public class MathCollegeIterator implements Iterator {
    // 确定Department是以什么方式存放
    private Department[] departments;
    // 遍历的位置
    private int position = 0;

    public MathCollegeIterator(Department[] departments) {
        this.departments = departments;
    }

    @Override
    public boolean hasNext() {
        return position < departments.length && departments[position] != null;
    }

    @Override
    public Object next() {
        Department department = departments[position];
        position++;
        return department;
    }

    @Override
    public void remove() {
    }
}

物理学院的迭代器实现类:

public class PhysicsCollegeIterator implements Iterator {
    // 物理学院是以List形式存放系
    private List<Department> departmentList;
    // 索引
    private int index = -1;

    public PhysicsCollegeIterator(List<Department> departmentList) {
        this.departmentList = departmentList;
    }

    @Override
    public boolean hasNext() {
        return index < departmentList.size() - 1;
    }

    @Override
    public Object next() {
        index++;
        return departmentList.get(index);
    }

    @Override
    public void remove() {
    }
}

学院的抽象类(对应到Aggregate):

public interface College {
    String getName();

    // 添加系
    void addDepartment(String name, String desc);

    // 创建迭代器
    Iterator createIterator();
}

数学学院MathCollege:

public class MathCollege implements College {
    private Department[] departments;
    // 保存当前数组的对象个数
    private int numberOfDepartment = 0;

    public MathCollege() {
        departments = new Department[5];
        addDepartment("高等数学", "树上挂了好多人");
        addDepartment("线性代数", "矩阵是个什么东西");
        addDepartment("概率统计", "博彩分析师");
    }

    @Override
    public String getName() {
        return "数学学院";
    }

    @Override
    public void addDepartment(String name, String desc) {
        departments[numberOfDepartment] = new Department(name, desc);
        numberOfDepartment++;
    }

    @Override
    public Iterator createIterator() {
        return new MathCollegeIterator(departments);
    }
}

物理学院PhysicsCollege:

public class PhysicsCollege implements College {
    private List<Department> departmentList;

    public PhysicsCollege() {
        departmentList = new ArrayList<>();
        addDepartment("理论力学", "牛顿的棺材板压不住了");
        addDepartment("量子力学", "上帝天天玩骰子");
        addDepartment("电动力学", "天才的麦克斯韦");
        addDepartment("热力学", "变与不变之道");
    }

    @Override
    public String getName() {
        return "物理学院";
    }

    @Override
    public void addDepartment(String name, String desc) {
        departmentList.add(new Department(name, desc));
    }

    @Override
    public Iterator createIterator() {
        return new PhysicsCollegeIterator(departmentList);
    }
}

为了Client端调用方便,我们写了一个OutputImpl类:

public class OutputImpl {
    // 学院集合
    private List<College> collegeList;

    public OutputImpl(List<College> collegeList) {
        this.collegeList = collegeList;
    }

    // 遍历所有学院,然后调用printDepartment输出各个学院的系
    public void printCollege() {
        Iterator<College> iterator = collegeList.iterator();
        while (iterator.hasNext()) {
            College college = iterator.next();
            System.out.println("==========" + college.getName() + "==========");
            printDepartment(college.createIterator());
        }
    }

    // 学院输出系
    public void printDepartment(Iterator iterator) {
        while (iterator.hasNext()) {
            Department department = (Department) iterator.next();
            System.out.println(department.getName());
        }
    }
}

Client调用:

public class Client {
    public static void main(String[] args) {
        // 创建学院
        List<College> collegeList = new ArrayList<>();
        collegeList.add(new MathCollege());
        collegeList.add(new PhysicsCollege());

        OutputImpl output = new OutputImpl(collegeList);
        output.printCollege();
    }
}

输出结果:

==========数学学院==========
高等数学
线性代数
概率统计
==========物理学院==========
理论力学
量子力学
电动力学
热力学
输出学院结构需求的类图

4 迭代器模式的特点

1)迭代器模式提供了一个统一的遍历对象的方法,调用方不需要再考虑聚合的类型,使用一种方法就可以遍历对象了。
2)隐藏了聚合的内部结构,调用方要遍历聚合时只能取迭代器,而不会知道聚合的具体组成。
3)满足单一职责原则,即一个类只有一个引起变化的原因。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,那么如果集合改变了,只影响到聚合的对象,而遍历方式改变的话,只影响迭代器。
4)每个聚合对象都需要一个迭代器,会产生多个迭代器以至于不好管理。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。