告白網(wǎng)站怎么做網(wǎng)站快速收錄技術(shù)
什么是迭代器模式
????????迭代器模式(Iterator pattern)是一種對象行為型設(shè)計模式,它提供了一種方法來順序訪問聚合對象中的元素,而又不暴露該對象的內(nèi)部表示,同時也可以將迭代邏輯與聚合對象的實現(xiàn)分離,增強了代碼的可維護性和可擴展性。
????????迭代器模式的特征如下:
- 迭代器模式允許一個聚合對象公開它的每一個元素,而又不暴露其內(nèi)部表示,即它提供了一種方法來遍歷聚合對象中的每一個元素,而不需要了解該對象的內(nèi)部結(jié)構(gòu)或?qū)崿F(xiàn)。
- 迭代器模式的主要目的是將迭代邏輯封裝在迭代器對象中,而不是將該邏輯嵌入到聚合對象中。這樣可以將迭代邏輯與聚合對象的實現(xiàn)分離,使得它們可以獨立地改變和擴展。
- 迭代器模式是通過定義一個迭代器接口來實現(xiàn)的。該接口提供了訪問和遍歷聚合對象的元素的方法。聚合對象則需要實現(xiàn)一個能夠創(chuàng)建相應(yīng)迭代器的接口。
迭代器模式的核心角色
- 迭代器接口(Iterator):定義了訪問和遍歷集合元素的方法,為使用者提供了一種方便的方式來遍歷集合中的元素,而不必關(guān)心集合的實現(xiàn)細節(jié),如:是否能夠繼續(xù)遍歷下一個元素、取出下一個元素等。
- 具體迭代器(ConcreteIterator):持有一個具體的集合,并且實現(xiàn)了迭代器接口,實際負責(zé)按照特定的順序遍歷集合中的元素,并將遍歷結(jié)果反饋給使用者。
- 集合接口(Aggregate):定義了創(chuàng)建迭代器的抽象方法,隱藏了具體集合的表示和實現(xiàn),具體的表示和實現(xiàn)由具體集合類來負責(zé)實現(xiàn);
- 具體集合(ConcreteAggregate):該類實現(xiàn)了集合接口,創(chuàng)建出具體的迭代器對象,供使用者通過迭代器來訪問和遍歷集合元素。當(dāng)然,作為具體集合,需要提供具體的添加、移除、查詢集合長度的具體方法;
迭代器模式如何實現(xiàn)
需求描述
????????回想在上大學(xué)的時候,老師在教學(xué)活動中都會擁有一個學(xué)生的花名冊,上面有學(xué)生的姓名、學(xué)號等信息,每次上課前都要先按照名冊上記錄的順序逐一點名,如果幫老師寫一個自動點名的程序,那么這個時候使用迭代器模式絕對是非常不錯的一個選擇。那么具體怎么實現(xiàn)呢?
實現(xiàn)方法
1、定義一個迭代器接口,即名冊迭代器接口,主要有兩個抽象方法:判斷是否下一個元素可以遍歷、遍歷取出下一個元素;
/*** 名刪除迭代器抽象接口* @param <T>*/
public interface RosterInterator<T> {/*** 是否有下一個元素* @return*/boolean hasNext();/*** 取出下一個元素* @return*/T next();
}
2、定義一個集合接口:抽象名冊接口,定義一個抽象方法:獲取名冊迭代器;
/*** 名冊*/
public interface Roster<T> {/*** 獲取迭代器* @return*/RosterInterator<T> getInterator();
}
3、定義具體的集合,即具體的學(xué)生名冊類,具體的學(xué)生名冊類除了正??梢酝鶎W(xué)生名冊上添加、移除學(xué)生,查詢學(xué)生名冊上人員數(shù)量方法外,還要實現(xiàn)抽象名冊接口的獲取名冊迭代器的方法,在方法中創(chuàng)建具體的迭代器對象;
/*** 學(xué)生類*/
@Data
public class Student {private String stuNo;private String name;public Student(String stuNo, String name) {this.stuNo = stuNo;this.name = name;}
}
/*** 學(xué)生名冊*/
@Data
public class StudentRoster implements Roster<Student>{/*** 學(xué)生對象集合*/private List<Student> list=new ArrayList<>();/*** 添加學(xué)生* @param student*/public void add(Student student){this.list.add(student);}/*** 移除學(xué)生* @param student*/public void remove(Student student){this.list.remove(student);}/*** 學(xué)生名冊學(xué)生對象數(shù)量* @return*/public Integer size(){return this.list.size();}@Overridepublic RosterInterator<Student> getInterator() {return new StudentRosterInterator(this);}
}
4、定義集合迭代器實現(xiàn),即具體的學(xué)生名冊迭代器,具體的學(xué)生迭代器會持有具體的學(xué)生名冊,并實現(xiàn)名冊迭代器定義的兩個抽象方法,即具體的判斷是否有下一個元素可以遍歷、遍歷取出下一個元素;
/*** 學(xué)生名冊迭代器*/
@Data
public class StudentRosterInterator implements RosterInterator<Student>{/*** 學(xué)生名冊*/private StudentRoster roster;/*** 索引位置*/private Integer index=0;public StudentRosterInterator(StudentRoster roster) {this.roster = roster;}@Overridepublic boolean hasNext() {return this.roster.size() > index;}@Overridepublic Student next() {Student student = this.roster.getList().get(index);index++;return student;}
}
5、編寫客戶端類
public class StudentClient {public static void main(String[] args) {StudentRoster studentRoster=new StudentRoster();Student stu1 = new Student("s001", "小明");Student stu2 = new Student("s002", "小紅");Student stu3 = new Student("s003", "小剛");studentRoster.add(stu1);studentRoster.add(stu2);studentRoster.add(stu3);RosterInterator<Student> rosterInterator=new StudentRosterInterator(studentRoster);while (rosterInterator.hasNext()) {Student student = rosterInterator.next();System.out.println(student.getStuNo()+":"+student.getName());}}
}
如何擴展
老師上課的時候會根據(jù)學(xué)生畫名冊點名,那么學(xué)校領(lǐng)導(dǎo)在給老師們開會的時候,有沒有可能也會點一個名,看年哪位老師沒有到?當(dāng)然會。假如也要幫校長實現(xiàn)一個對老師們的點名程序,應(yīng)該怎么在原先的基礎(chǔ)上擴展呢?其實很簡單,保持原有的抽象名冊迭代器接口、抽象名冊接口不變,再分別實現(xiàn)老師畫名冊、老師畫名冊迭代器就可。而且這一過程完全符合開閉原則,不會對原來的程序造成任何影響,這就是設(shè)計模式的魅力。
/*** 老師類*/
@Data
public class Teacher {private String teacNo;private String name;public Teacher(String teacNo, String name) {this.teacNo = teacNo;this.name = name;}
}
/*** 老師名冊*/
@Data
public class TeacherRoster implements Roster<Teacher>{/*** 老師對象集合*/private List<Teacher> list=new ArrayList<>();/*** 添加老師* @param teacher*/public void add(Teacher teacher){this.list.add(teacher);}/*** 移除老師* @param teacher*/public void remove(Teacher teacher){this.list.remove(teacher);}/*** 老師名冊中對象數(shù)量* @return*/public Integer size(){return this.list.size();}@Overridepublic RosterInterator<Teacher> getInterator() {return new TeacherRosterInterator(this) ;}
}
/*** 老師名冊迭代器*/
@Data
public class TeacherRosterInterator implements RosterInterator<Teacher> {private TeacherRoster teacherRoster;private Integer index = 0;public TeacherRosterInterator(TeacherRoster teacherRoster) {this.teacherRoster = teacherRoster;}@Overridepublic boolean hasNext() {return this.teacherRoster.size() > index;}@Overridepublic Teacher next() {Teacher teacher = this.teacherRoster.getList().get(index);index++;return teacher;}
}
public class TeacherClent {public static void main(String[] args) {TeacherRoster teacherRoster=new TeacherRoster();Teacher t1 = new Teacher("t001", "王老師");Teacher t2 = new Teacher("t002", "李老師");Teacher t3 = new Teacher("t003", "張老師");teacherRoster.add(t1);teacherRoster.add(t2);teacherRoster.add(t3);RosterInterator<Teacher> rosterInterator=new TeacherRosterInterator(teacherRoster);while (rosterInterator.hasNext()) {Teacher teacher = rosterInterator.next();System.out.println(teacher.getTeacNo()+":"+teacher.getName());}}
}
迭代器模式的適用場景
????????業(yè)務(wù)場景具有下面的特征就可以使用迭代器模式:
- 需要遍歷集合對象中的元素,而不暴露該對象的內(nèi)部表示的場景。通過使用迭代器模式,可以在不暴露集合對象內(nèi)部結(jié)構(gòu)的情況下,順序訪問集合對象中的各個元素。
- 需要為遍歷不同的集合結(jié)構(gòu)提供統(tǒng)一接口的場景。迭代器模式可以提供一種統(tǒng)一的接口,用于遍歷不同的集合結(jié)構(gòu),從而使得代碼更加靈活和可擴展。
有沒有比較具體的業(yè)務(wù)場景示例呢?當(dāng)然有,比如:
- 在物流系統(tǒng)中,可以使用迭代器模式來遍歷物品。例如,在傳送帶上,不管傳送的是什么物品,都被打包成一個一個的箱子并且有一個統(tǒng)一的二維碼。這樣我們不需要關(guān)心箱子里是什么物品,只需要一個一個檢查發(fā)送的目的地即可。
- 在圖片播放器中,可以使用迭代器模式來遍歷圖片。這樣可以在不暴露圖片內(nèi)部結(jié)構(gòu)的情況下,順序訪問圖片中的各個元素。
- 圖書館管理系統(tǒng):在圖書館中,需要對書籍進行遍歷,可以使用迭代器模式來處理。通過定義一個統(tǒng)一的迭代器接口,不同的數(shù)據(jù)結(jié)構(gòu)(如數(shù)組、鏈表等)都可以使用相同的迭代器接口來遍歷書籍,同時保持內(nèi)部實現(xiàn)的封裝。
- 電商網(wǎng)站:在電商網(wǎng)站中,通常需要對商品進行展示和遍歷。使用迭代器模式可以實現(xiàn)對商品的順序訪問,而不暴露商品內(nèi)部表示。
- 金融系統(tǒng):在金融系統(tǒng)中,需要對賬戶、交易等進行處理。使用迭代器模式可以實現(xiàn)對賬戶或交易的順序訪問,而不暴露其內(nèi)部表示。
- 音樂播放器:在音樂播放器中,需要遍歷音樂庫中的歌曲。使用迭代器模式可以實現(xiàn)對歌曲的順序訪問,而不暴露歌曲內(nèi)部表示。
總結(jié)
優(yōu)點
- 分離集合與迭代邏輯:迭代器模式將集合對象與遍歷邏輯分離,使得它們可以獨立變化。集合對象只需要實現(xiàn)迭代器接口,而客戶端只需要通過迭代器進行遍歷操作,從而實現(xiàn)了解耦和模塊化。
- 統(tǒng)一遍歷接口:迭代器模式定義了一組統(tǒng)一的遍歷接口,使得客戶端可以以相同的方式對待不同類型的集合對象。無論是數(shù)組、鏈表、樹狀結(jié)構(gòu)還是其他自定義集合,只要它們提供了符合迭代器接口的迭代器對象,就可以使用迭代器模式進行遍歷,提高了代碼的靈活性和可復(fù)用性。
- 簡化客戶端代碼:使用迭代器模式可以簡化客戶端代碼,減少了對集合內(nèi)部結(jié)構(gòu)的直接操作,只需要通過迭代器對象進行遍歷操作。
缺點
- 可能增加代碼復(fù)雜度:使用迭代器模式可能會增加一些額外的代碼復(fù)雜度,例如需要定義迭代器接口、具體迭代器實現(xiàn)類等。
- 限制集合對象的類型:迭代器模式通常只適用于集合類型的聚合對象,不能很好地處理其他類型的聚合對象,例如樹形結(jié)構(gòu)、圖形結(jié)構(gòu)等。
- 可能增加內(nèi)存開銷:使用迭代器模式可能會增加一些額外的內(nèi)存開銷,例如需要創(chuàng)建迭代器對象等。
????????總之,迭代器模式在許多業(yè)務(wù)場景中都有應(yīng)用,可以實現(xiàn)對集合對象的順序訪問,而不暴露其內(nèi)部表示,可以使得代碼更加清晰、簡潔、易于維護。