迭代器模式(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());
}
}
}
业务场景具有下面的特征就可以使用迭代器模式:
有没有比较具体的业务场景示例呢?当然有,比如:
总之,迭代器模式在许多业务场景中都有应用,可以实现对集合对象的顺序访问,而不暴露其内部表示,可以使得代码更加清晰、简洁、易于维护。