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

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

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

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);
        }

    }


    /**
     * 學生類
     */
    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ù)據格式變了

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);
        }
    }


    /**
     * 學生類
     */
    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ù)組 --> map彤侍,或者其他的改變肠缨,那么迭代的代碼,就需要發(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();
    }

    /**
     * 學生類
     */
    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 相當于數(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ù)據闷袒。
         * @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ù)組是否還有下一個元素
         * 假設此時 index = 0坑律,classroom 的 length = 2, 那么還有下一個元素霜运,數(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ù)組集合當前的元素池摧。
         * 從數(shù)組中獲取當前這個學生焦除,同時將 index 往后移動一位
         * 比如 一開始 index 是0,數(shù)組長度是 2
         * 此時遍歷獲取第一個學生之后作彤,返回數(shù)組的 0 元素膘魄,然后將 index 變成 1。
         * @return
         */
        public Object next() {
            Student student = classroom.getStudent(index);
            index++;
            return student;
        }

    }

}

1.4 使用迭代器模式實現(xiàn) -- 集合中數(shù)據變成 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();
    }

    /**
     * 學生類
     */
    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 相當于數(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ù)據。
         * @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ù)組是否還有下一個元素
         * 假設此時 index = 0绢慢,classroom 的 length = 2灿渴, 那么還有下一個元素,數(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ù)組集合當前的元素棘幸。
         * 從數(shù)組中獲取當前這個學生,同時將 index 往后移動一位
         * 比如 一開始 index 是0倦零,數(shù)組長度是 2
         * 此時遍歷獲取第一個學生之后误续,返回數(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();
    }

    /**
     * 學生類
     */
    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 相當于數(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ù)據诞帐。
         * @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ù)組是否還有下一個元素
         * 假設此時 index = 0欣尼,classroom 的 length = 2, 那么還有下一個元素,數(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ù)組集合當前的元素册倒。
         * 從數(shù)組中獲取當前這個學生,同時將 index 往后移動一位
         * 比如 一開始 index 是0磺送,數(shù)組長度是 2
         * 此時遍歷獲取第一個學生之后驻子,返回數(shù)組的 0 元素,然后將 index 變成 1估灿。
         * @return
         */
        public Object next() {
            Student student = classroom.getStudent(index);
            index++;
            return student;
        }
    }
}

總結

面向Iterator接口編程崇呵,無論底層的數(shù)據結構和迭代算法如何變化,調用者都不用修改代碼馅袁。

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

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市付材,隨后出現(xiàn)的幾起案子朦拖,更是在濱河造成了極大的恐慌,老刑警劉巖厌衔,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件璧帝,死亡現(xiàn)場離奇詭異,居然都是意外死亡富寿,警方通過查閱死者的電腦和手機睬隶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來页徐,“玉大人苏潜,你說我怎么就攤上這事”溆拢” “怎么了恤左?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵贴唇,是天一觀的道長。 經常有香客問我飞袋,道長戳气,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任巧鸭,我火速辦了婚禮瓶您,結果婚禮上,老公的妹妹穿的比我還像新娘纲仍。我一直安慰自己呀袱,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布郑叠。 她就那樣靜靜地躺著夜赵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锻拘。 梳的紋絲不亂的頭發(fā)上油吭,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音署拟,去河邊找鬼。 笑死歌豺,一個胖子當著我的面吹牛推穷,可吹牛的內容都是我干的。 我是一名探鬼主播类咧,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼馒铃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了痕惋?” 一聲冷哼從身側響起区宇,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎值戳,沒想到半個月后议谷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡堕虹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年卧晓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赴捞。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡逼裆,死狀恐怖,靈堂內的尸體忽然破棺而出赦政,到底是詐尸還是另有隱情胜宇,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站桐愉,受9級特大地震影響封寞,放射性物質發(fā)生泄漏。R本人自食惡果不足惜仅财,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一狈究、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盏求,春花似錦抖锥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荆烈,卻和暖如春拯勉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背憔购。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工宫峦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玫鸟。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓导绷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親屎飘。 傳聞我的和親對象是個殘疾皇子妥曲,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容