設(shè)計模式之迭代器(iterator)模式

設(shè)計模式之迭代器(iterator)模式

需求: 假設(shè),有一個教室類,里面包含了一堆學(xué)生,現(xiàn)在要遍歷教室里的學(xué)生,怎么操作?

1.1 不使用迭代器模式的方式

public class WithoutIteratorPatternDemo {

    public static void main(String[] args) {
        Student student1 = new Student("小李");
        Student student2 = new Student("小吳");

        Student[] students = new Student[2];
        students[0] = student1;
        students[1] = student2;

        Classroom classroom = new Classroom();
        classroom.setStudents(students);

        Student[] studentsResults = classroom.getStudents();

        for (Student student : studentsResults) {
            System.out.println(student);
        }

    }


    /**
     * 學(xué)生類
     */
    public static class Student{

        public 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 Student[] students;

        public Student[] getStudents() {
            return students;
        }

        public void setStudents(Student[] students) {
            this.students = students;
        }

    }

}

1.2 不使用迭代器模式的方式 -- 集合中數(shù)據(jù)格式變了

public class WithoutIteratorPatternDemo2 {

    public static void main(String[] args) {
        Student student1 = new Student("小李");
        Student student2 = new Student("小吳");

        Map<String, Student> students = new HashMap<String, Student>();
        students.put(student1.getName(), student1);
        students.put(student2.getName(), student2);


        Classroom classroom = new Classroom();
        classroom.setStudents(students);

        Map<String, Student> studentsResults = classroom.getStudents();
        for (Student studentsResult : studentsResults.values()) {
            System.out.println(studentsResult);
        }
    }


    /**
     * 學(xué)生類
     */
    public static class Student{

        public 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 + '\'' +
                    '}';
        }
    }

    /**
     * 教室類 -- 格式發(fā)生改變
     */
    public static class Classroom {
        private Map<String, Student> students;

        public void setStudents(Map<String, Student> students) {
            this.students = students;
        }

        public Map<String, Student> getStudents() {
            return students;
        }
    }

}

不使用設(shè)計模式的缺點:

如果不使用任何設(shè)計模式,直接去遍歷一個類中的集合,一旦這個類中對集合的使用改變了,比如上面的例子: 從數(shù)組 --> map,或者其他的改變,那么迭代的代碼,就需要發(fā)生改動。

如果代碼和邏輯比較復(fù)雜,集合類的實現(xiàn)和遍歷代碼的實現(xiàn)由不同的人開發(fā)或不同的模塊使用,就會有比較大的影響,可維護性和可擴展性比較差。

1.3 使用迭代器模式實現(xiàn)

package com.lucky.pattern.iterator;

/**
 * @author: LIJY
 * @Description: iterator (迭代器)模式 -- 用迭代器模式實現(xiàn)
 * @Date: 2021/10/1 17:03
 */
public class IteratorDesignPatternDemo {

    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 iterator = classroom.iterator();
        while (iterator.hasNext()){
            Student student = (Student) iterator.next();
            System.out.println(student);
        }

    }

    /**
     * 定義一個迭代器
     */
    public interface Iterator {
        public abstract boolean hasNext();
        public abstract Object next();
    }

    /**
     * 定義一個集合類
     */
    public interface Aggregate {
        public abstract Iterator iterator();
    }

    /**
     * 學(xué)生類
     */
    public static class Student{

        public 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 Student[] students;
        // last 相當(dāng)于數(shù)組的長度
        private int last = 0;

        public Classroom(int size) {
            this.students = new Student[size];
        }

        public Student getStudent(int index) {
            return students[index];
        }

        public void addStudent(Student student) {
            this.students[last] = student;
            last ++;
        }

        public int getLength() {
            return last;
        }

        /**
         * 返回一個教室迭代器,其中封裝了教室自己,讓迭代器可以獲取教室中的數(shù)據(jù)。
         * @return
         */
        public Iterator iterator() {
            return new ClassroomIterator(this);
        }
    }

    /**
     * 教室迭代器
     */
    public static class ClassroomIterator implements Iterator {

        private Classroom classroom;
        private int index;

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

        /**
         * 判斷數(shù)組是否還有下一個元素
         * 假設(shè)此時 index = 0,classroom 的 length = 2, 那么還有下一個元素,數(shù)組沒有遍歷完。
         * 假設(shè)此時 index = 2,classroom 的 length = 2, 那么就沒有下一個元素。 classroom 可以遍歷的數(shù)組的 offest 只能是 0 和 1
         * @return
         */
        public boolean hasNext() {
            if(index < classroom.getLength()) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * 獲取數(shù)組集合當(dāng)前的元素。
         * 從數(shù)組中獲取當(dāng)前這個學(xué)生,同時將 index 往后移動一位
         * 比如 一開始 index 是0,數(shù)組長度是 2
         * 此時遍歷獲取第一個學(xué)生之后,返回數(shù)組的 0 元素,然后將 index 變成 1。
         * @return
         */
        public Object next() {
            Student student = classroom.getStudent(index);
            index++;
            return student;
        }

    }

}

1.4 使用迭代器模式實現(xiàn) -- 集合中數(shù)據(jù)變成 List

package com.lucky.pattern.iterator;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: LIJY
 * @Description: iterator (迭代器)模式 -- 用迭代器模式實現(xiàn)
 * @Date: 2021/10/1 17:03
 */
public class IteratorDesignPatternDemo2 {

    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 iterator = classroom.iterator();
        while (iterator.hasNext()){
            Student student = (Student) iterator.next();
            System.out.println(student);
        }

    }

    /**
     * 定義一個迭代器
     */
    public interface Iterator {
        public abstract boolean hasNext();
        public abstract Object next();
    }

    /**
     * 定義一個集合類
     */
    public interface Aggregate {
        public abstract Iterator iterator();
    }

    /**
     * 學(xué)生類
     */
    public static class Student{

        public 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 Student[] students;
        private List<Student> students;

        /**
         * last 相當(dāng)于數(shù)組的長度
         */
        private int last = 0;

        public Classroom(int size) {
//            this.students = new Student[size];
            this.students = new ArrayList<Student>(2);
        }

        public Student getStudent(int index) {
//            return students[index];
            return students.get(index);
        }

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

        public int getLength() {
            return last;
        }

        /**
         * 返回一個教室迭代器,其中封裝了教室自己,讓迭代器可以獲取教室中的數(shù)據(jù)。
         * @return
         */
        public Iterator iterator() {
            return new ClassroomIterator(this);
        }
    }

    /**
     * 教室迭代器
     */
    public static class ClassroomIterator implements Iterator {

        private Classroom classroom;
        private int index;

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

        /**
         * 判斷數(shù)組是否還有下一個元素
         * 假設(shè)此時 index = 0,classroom 的 length = 2, 那么還有下一個元素,數(shù)組沒有遍歷完。
         * 假設(shè)此時 index = 2,classroom 的 length = 2, 那么就沒有下一個元素。 classroom 可以遍歷的數(shù)組的 offest 只能是 0 和 1
         * @return
         */
        public boolean hasNext() {
            if(index < classroom.getLength()) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * 獲取數(shù)組集合當(dāng)前的元素。
         * 從數(shù)組中獲取當(dāng)前這個學(xué)生,同時將 index 往后移動一位
         * 比如 一開始 index 是0,數(shù)組長度是 2
         * 此時遍歷獲取第一個學(xué)生之后,返回數(shù)組的 0 元素,然后將 index 變成 1。
         * @return
         */
        public Object next() {
            Student student = classroom.getStudent(index);
            index++;
            return student;
        }
    }
}

1.5 使用 JDK 封裝好的 Iterator

package com.lucky.pattern.iterator;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: LIJY
 * @Description: iterator (迭代器)模式 -- 用迭代器模式實現(xiàn)
 * @Date: 2021/10/1 17:03
 */
public class IteratorDesignPatternDemo2 {

    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 iterator = classroom.iterator();
        java.util.Iterator iterator = classroom.iterator();
        while (iterator.hasNext()){
            Student student = (Student) iterator.next();
            System.out.println(student);
        }

    }

    /**
     * 定義一個迭代器
     */
    public interface Iterator {
        public abstract boolean hasNext();
        public abstract Object next();
    }

    /**
     * 定義一個集合類
     */
    public interface Aggregate {
//        public abstract Iterator iterator();
        public abstract java.util.Iterator iterator();
    }

    /**
     * 學(xué)生類
     */
    public static class Student{

        public 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 Student[] students;
        private List<Student> students;

        /**
         * last 相當(dāng)于數(shù)組的長度
         */
        private int last = 0;

        public Classroom(int size) {
//            this.students = new Student[size];
            this.students = new ArrayList<Student>(2);
        }

        public Student getStudent(int index) {
//            return students[index];
            return students.get(index);
        }

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

        public int getLength() {
            return last;
        }

        /**
         * 返回一個教室迭代器,其中封裝了教室自己,讓迭代器可以獲取教室中的數(shù)據(jù)。
         * @return
         */
//        public Iterator iterator() {
//            return new ClassroomIterator(this);
//        }


        public java.util.Iterator iterator() {
            return students.iterator();
        }
    }

    /**
     * 教室迭代器
     */
    public static class ClassroomIterator implements Iterator {

        private Classroom classroom;
        private int index;

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

        /**
         * 判斷數(shù)組是否還有下一個元素
         * 假設(shè)此時 index = 0,classroom 的 length = 2, 那么還有下一個元素,數(shù)組沒有遍歷完。
         * 假設(shè)此時 index = 2,classroom 的 length = 2, 那么就沒有下一個元素。 classroom 可以遍歷的數(shù)組的 offest 只能是 0 和 1
         * @return
         */
        public boolean hasNext() {
            if(index < classroom.getLength()) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * 獲取數(shù)組集合當(dāng)前的元素。
         * 從數(shù)組中獲取當(dāng)前這個學(xué)生,同時將 index 往后移動一位
         * 比如 一開始 index 是0,數(shù)組長度是 2
         * 此時遍歷獲取第一個學(xué)生之后,返回數(shù)組的 0 元素,然后將 index 變成 1。
         * @return
         */
        public Object next() {
            Student student = classroom.getStudent(index);
            index++;
            return student;
        }
    }
}

總結(jié)

面向Iterator接口編程,無論底層的數(shù)據(jù)結(jié)構(gòu)和迭代算法如何變化,調(diào)用者都不用修改代碼。

其實一般很少自己寫這個 iterator 模式的,一般都是在集合編程中使用,尤其是如果要對集合元素遍歷過程中做插入刪除操作,那就用iterator,JDK本身已經(jīng)封裝好了iterator模式,如果要對某個類中的集合進行遍歷,由那個集合類返回一個iterator回來,我們統(tǒng)一面向iterator迭代器接口來編程遍歷,提高系統(tǒng)整體的可維護性,可擴展性。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容