设计模式之迭代模式
场景:
当一个聚集对象需要被遍历,且被遍历的方式需要与聚集对象解耦的情况下,迭代器模式是不二之选。由于java语言本身带有众多集合类,如List、Set、Map等,这些集合内部都有迭代器,所以迭代模式很少用,除非自己定义一个容器。
特点:
迭代器模式分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样做的好处就是既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。
实际就是封装一个自己的集合迭代器
示例场景
有一个教室类,里面包含了一堆学生,现在要遍历教室里的学生信息。
未使用迭代模式时
public class NoIteratorPattern {
public static void main(String[] args) {
Classroom classroom = new Classroom();
Student student1 = new Student("张三");
classroom.addStudent(student1);
Student student2 = new Student("李四");
classroom.addStudent(student2);
List<Student> students = classroom.getStudents();
for(Student student : students) {
System.out.println(student);
}
}
public static class Student {
private 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 final List<Student> students;
public Classroom(){
this.students = new ArrayList<>();
}
public List<Student> getStudents() {
return students;
}
public void addStudent(Student students){
this.students.add(students);
}
}
}
此时如果需要改为数组和迭代器的实现,同时业务逻辑复杂的话,则调用者也需要改动自己的代码,这样的维护性差。
使用迭代模式
public class IteratorPattern {
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<Student> iterator = classroom.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
public interface Iterator<T>{
/**
* 是否有下一个
* @return 返回结果
*/
boolean hasNext();
/**
* 获取下一个
* @return 返回下一个
*/
T next();
}
public interface Aggregate{
/**
* 迭代器
* @return 返回一个迭代器
*/
Iterator<Student> iterator();
}
public static class Student {
private 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 final List<Student> students;
private int last = 0;
public Classroom(int size){
students = new ArrayList<>();
}
public Student getStudent(int index){
return this.students.get(index);
}
public void addStudent(Student student){
this.students.add(student);
last++;
}
public int getLast() {
return last;
}
@Override
public Iterator<Student> iterator() {
return new ClassroomIterator(this);
}
}
public static class ClassroomIterator implements Iterator<Student>{
private final Classroom classroom;
private int index;
public ClassroomIterator(Classroom classroom){
this.classroom = classroom;
this.index = 0;
}
@Override
public boolean hasNext() {
return this.index<this.classroom.getLast();
}
@Override
public Student next() {
Student student = this.classroom.getStudent(index);
this.index++;
return student;
}
}
}
使用迭代模式后,当我们需要更改内部实现时,调用者几乎不用修改自己的代码即可使用。