设计模式之迭代模式

场景:

当一个聚集对象需要被遍历,且被遍历的方式需要与聚集对象解耦的情况下,迭代器模式是不二之选。由于java语言本身带有众多集合类,如List、Set、Map等,这些集合内部都有迭代器,所以迭代模式很少用,除非自己定义一个容器。

特点:

迭代器模式分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样做的好处就是既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。

实际就是封装一个自己的集合迭代器

示例场景

有一个教室类,里面包含了一堆学生,现在要遍历教室里的学生信息。

未使用迭代模式时

public class NoIteratorPattern {

    public static void main(String[] args) {
        Classroom classroom = new Classroom();

        Student student1 = new Student("张三");
        classroom.addStudent(student1);

        Student student2 = new Student("李四");
        classroom.addStudent(student2);

        List<Student> students = classroom.getStudents();
        for(Student student : students) {
            System.out.println(student);
        }
    }

    public static class Student {

        private String name;

        public Student(String name){
            this.name = name;
        }

        public String getName() {
            return name;
        }

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

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    public static class Classroom {

        private final List<Student> students;

        public Classroom(){
            this.students = new ArrayList<>();
        }

        public List<Student> getStudents() {
            return students;
        }
        
        public void addStudent(Student students){
            this.students.add(students);
        }

    }
}

此时如果需要改为数组和迭代器的实现,同时业务逻辑复杂的话,则调用者也需要改动自己的代码,这样的维护性差。

使用迭代模式

public class IteratorPattern {

    public static void main(String[] args) {
        Student student1 = new Student("张三");
        Student student2 = new Student("李四");

        Classroom classroom = new Classroom(2);
        classroom.addStudent(student1);
        classroom.addStudent(student2);

        Iterator<Student> iterator = classroom.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

    public interface Iterator<T>{

        /**
        * 是否有下一个
        * @return 返回结果
        */
        boolean hasNext();

        /**
        * 获取下一个
        * @return 返回下一个
        */
        T next();
    }

    public interface Aggregate{
        /**
        * 迭代器
        * @return 返回一个迭代器
        */
        Iterator<Student> iterator();
    }
    
    public static class Student {

        private String name;

        public Student(String name){
            this.name = name;
        }

        public String getName() {
            return name;
        }

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

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    public static class Classroom implements Aggregate {

        private final List<Student> students;

        private int last = 0;

        public Classroom(int size){
            students = new ArrayList<>();
        }

        public Student getStudent(int index){
            return this.students.get(index);
        }

        public void addStudent(Student student){
            this.students.add(student);
            last++;
        }

        public int getLast() {
            return last;
        }

        @Override
        public Iterator<Student> iterator() {
            return new ClassroomIterator(this);
        }
    }

    public static class ClassroomIterator implements Iterator<Student>{

        private final Classroom classroom;

        private int index;

        public ClassroomIterator(Classroom classroom){
            this.classroom = classroom;
            this.index = 0;
        }

        @Override
        public boolean hasNext() {
            return this.index<this.classroom.getLast();
        }

        @Override
        public Student next() {
            Student student = this.classroom.getStudent(index);
            this.index++;
            return student;
        }
    }
}

使用迭代模式后,当我们需要更改内部实现时,调用者几乎不用修改自己的代码即可使用。

posted @ 2020-08-08 17:10  起岸星辰  阅读(240)  评论(0编辑  收藏  举报