迭代器模式(Iterator pattern)是一种对象行为型设计模式,它提供了一种方法来顺序访问聚合对象中的元素,而又不暴露该对象的内部表示,同时也可以将迭代逻辑与聚合对象的实现分离,增强了代码的可维护性和可扩展性。
迭代器模式的特征如下:
回想在上大学的时候,老师在教学活动中都会拥有一个学生的花名册,上面有学生的姓名、学号等信息,每次上课前都要先按照名册上记录的顺序逐一点名,如果帮老师写一个自动点名的程序,那么这个时候使用迭代器模式绝对是非常不错的一个选择。那么具体怎么实现呢?
1、定义一个迭代器接口,即名册迭代器接口,主要有两个抽象方法:判断是否下一个元素可以遍历、遍历取出下一个元素;
- /**
- * 名删除迭代器抽象接口
- * @param
- */
- public interface RosterInterator
{ - /**
- * 是否有下一个元素
- * @return
- */
- boolean hasNext();
-
- /**
- * 取出下一个元素
- * @return
- */
- T next();
- }
2、定义一个集合接口:抽象名册接口,定义一个抽象方法:获取名册迭代器;
- /**
- * 名册
- */
- public interface Roster
{ - /**
- * 获取迭代器
- * @return
- */
- RosterInterator
getInterator(); - }
3、定义具体的集合,即具体的学生名册类,具体的学生名册类除了正常可以往学生名册上添加、移除学生,查询学生名册上人员数量方法外,还要实现抽象名册接口的获取名册迭代器的方法,在方法中创建具体的迭代器对象;
- /**
- * 学生类
- */
- @Data
- public class Student {
- private String stuNo;
- private String name;
-
- public Student(String stuNo, String name) {
- this.stuNo = stuNo;
- this.name = name;
- }
- }
- /**
- * 学生名册
- */
- @Data
- public class StudentRoster implements Roster
{ - /**
- * 学生对象集合
- */
- private List
list=new ArrayList<>(); -
- /**
- * 添加学生
- * @param student
- */
- public void add(Student student){
- this.list.add(student);
- }
-
- /**
- * 移除学生
- * @param student
- */
- public void remove(Student student){
- this.list.remove(student);
- }
-
- /**
- * 学生名册学生对象数量
- * @return
- */
- public Integer size(){
- return this.list.size();
- }
- @Override
- public RosterInterator
getInterator() { - return new StudentRosterInterator(this);
- }
- }
4、定义集合迭代器实现,即具体的学生名册迭代器,具体的学生迭代器会持有具体的学生名册,并实现名册迭代器定义的两个抽象方法,即具体的判断是否有下一个元素可以遍历、遍历取出下一个元素;
- /**
- * 学生名册迭代器
- */
- @Data
- public class StudentRosterInterator implements RosterInterator
{ - /**
- * 学生名册
- */
- private StudentRoster roster;
- /**
- * 索引位置
- */
- private Integer index=0;
-
- public StudentRosterInterator(StudentRoster roster) {
- this.roster = roster;
- }
-
- @Override
- public boolean hasNext() {
- return this.roster.size() > index;
- }
-
- @Override
- public 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
rosterInterator=new StudentRosterInterator(studentRoster); - while (rosterInterator.hasNext()) {
- Student student = rosterInterator.next();
- System.out.println(student.getStuNo()+":"+student.getName());
- }
- }
- }
老师上课的时候会根据学生画名册点名,那么学校领导在给老师们开会的时候,有没有可能也会点一个名,看年哪位老师没有到?当然会。假如也要帮校长实现一个对老师们的点名程序,应该怎么在原先的基础上扩展呢?其实很简单,保持原有的抽象名册迭代器接口、抽象名册接口不变,再分别实现老师画名册、老师画名册迭代器就可。而且这一过程完全符合开闭原则,不会对原来的程序造成任何影响,这就是设计模式的魅力。
- /**
- * 老师类
- */
- @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
{ - /**
- * 老师对象集合
- */
- private List
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);
- }
-
- /**
- * 老师名册中对象数量
- * @return
- */
- public Integer size(){
- return this.list.size();
- }
-
- @Override
- public RosterInterator
getInterator() { - return new TeacherRosterInterator(this) ;
- }
- }
- /**
- * 老师名册迭代器
- */
- @Data
- public class TeacherRosterInterator implements RosterInterator
{ -
- private TeacherRoster teacherRoster;
- private Integer index = 0;
-
-
- public TeacherRosterInterator(TeacherRoster teacherRoster) {
- this.teacherRoster = teacherRoster;
- }
-
- @Override
- public boolean hasNext() {
- return this.teacherRoster.size() > index;
- }
-
- @Override
- public 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
rosterInterator=new TeacherRosterInterator(teacherRoster); - while (rosterInterator.hasNext()) {
- Teacher teacher = rosterInterator.next();
- System.out.println(teacher.getTeacNo()+":"+teacher.getName());
- }
- }
- }
业务场景具有下面的特征就可以使用迭代器模式:
有没有比较具体的业务场景示例呢?当然有,比如:
总之,迭代器模式在许多业务场景中都有应用,可以实现对集合对象的顺序访问,而不暴露其内部表示,可以使得代码更加清晰、简洁、易于维护。