目录
一、基础概念
二、UML类图
三、角色设计
四、案例分析
五、总结
迭代器模式是一种常用的设计模式,它主要用于遍历集合对象,提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
举个简单的比喻,聚合对象像一个存放苹果的篮子,迭代器就像篮子边上的搬运工,专门负责把苹果一个一个取出来。客户端只需要找到搬运工,然后不停地让他取出苹果就可以了,而不需要关心篮子里面是怎么存放的。这样既方便客户端使用,也屏蔽了聚合对象内部的复杂性!
角色 | 描述 |
---|---|
抽象聚合角色 | 定义存创建、添加、获取等迭代器对象的接口 |
具体聚合角色 | 抽象聚合角色的实现类,返回一个具体迭代器实例 |
抽象迭代器角色 | 定义访问和遍历聚合元素的接口,通常包裹hashNext()和next()方法 |
具体迭代器角色 | 实现抽象迭代器接口中所定义的方法,完成聚合对象的遍历,记录遍历的当前为止 |
客户端角色 | 用于使用迭代器遍历聚合对象 |
用迭代器模式模拟一个学生管理系统,主要内容如下:
1、定义Student类,表示学生信息。
2、定义StudentAggregate接口,作为学生集合的抽象接口。
3、实现StudentAggregateImpl类,具体的学生集合,使用List存储Student。
4、定义Iterator接口,规定迭代器的通用方法。
5、实现StudentIterator类,具体的学生迭代器。
6、在客户端代码中,通过迭代器遍历StudentAggregateImpl中的学生集合。
通过迭代器模式实现对学生集合的遍历,同时隐藏学生集合的具体实现细节,示例代码如下:
定义学生类:
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
学生集合抽象聚合类:
public interface StudentAggregate {
public Iterator createIterator();
public int getNumberOfStudents();
public Student getStudent(int index);
public void addStudent(Student student);
}
学生集合具体聚合角色:
import java.util.ArrayList;
import java.util.List;
public class StudentAggregateImpl implements StudentAggregate{
private List students;
public StudentAggregateImpl() {
students = new ArrayList<>();
}
@Override
public Iterator createIterator() {
return new StudentIterator(this);
}
@Override
public int getNumberOfStudents() {
return students.size();
}
@Override
public Student getStudent(int index) {
return students.get(index);
}
@Override
public void addStudent(Student student) {
students.add(student);
}
}
抽象迭代器角色:
public interface Iterator {
public boolean hasNext();
public Student next();
}
学生具体迭代器角色:
public class StudentIterator implements Iterator {
private StudentAggregate studentAggregate;
private int index;
public StudentIterator(StudentAggregate studentAggregate) {
this.studentAggregate = studentAggregate;
}
@Override
public boolean hasNext() {
return (index < studentAggregate.getNumberOfStudents());
}
@Override
public Student next() {
return studentAggregate.getStudent(index++);
}
}
客户端:
public class Client {
public static void main(String[] args) {
//使用示例
StudentAggregate students = new StudentAggregateImpl();
// 添加学生
Student john = new Student("John", 18);
Student mike = new Student("Mike", 18);
students.addStudent(john);
students.addStudent(mike);
Iterator iterator = students.createIterator();
while(iterator.hasNext()) {
Student student = iterator.next();
System.out.println(student.getName());
}
}
}
运行结果如下:
这个迭代器模式在学生管理示例中的执行逻辑过程:
1、定义Student类,用于表示学生信息。
2、定义StudentAggregate接口,作为抽象学生集合类,声明管理学生的通用方法。
3、实现StudentAggregateImpl类,具体的学生集合,使用List存储Student对象。
4、定义Iterator接口,规定迭代器的通用方法。
5、实现StudentIterator类,具体的学生迭代器,持有对StudentAggregate的引用。
6、创建StudentAggregateImpl对象students,表示具体的学生集合。
7、调用students的addStudent()方法,向集合中添加学生。
8、调用students的createIterator()方法,获取迭代器对象。
9、使用迭代器的hasNext()和next()方法遍历students集合,访问其中的学生对象。
10、在整个过程中,客户端代码都只与Iterator接口发生依赖,而不需了解学生集合的具体实现/
这样通过迭代器模式可以实现学生集合的遍历,同时也达到了对访问学生集合的控制和集合内部表示的封装。
优点:
1、隔离了集合对象的遍历行为,抽象出一个迭代器类来负责迭代元素。
2、提供了一种方法顺序访问一个聚合对象中的各个元素,而又无需暴露该对象的内部表示。
3、迭代器简化了聚合类。客户端如果需要遍历聚合对象,只需要初始化一个迭代器,不需要知道聚合对象内部的具体实现。
4、在同一个聚合类中可以定义多个遍历方式,通过不同的迭代器来实现。
5、符合单一职责原则。
6、实现了集合类的常用遍历算法,容易扩展和维护。
缺点:
1、增加了类的个数,代码复杂度会增加,需要维护更多的代码。
2、多态性能损耗。遍历时需要进行多次虚函数调用,遍历效率降低。
3、遍历算法复用性差。每次遍历都需要创建新的迭代器实例,无法重用已定义好的遍历算法。
应用场景:
1、访问一个聚合对象的内容而无需暴露它的内部表示。
2、为遍历不同的集合结构提供一个统一的接口(即支持多态迭代)。
3、提供一种方法顺序访问一个聚合对象中的各个元素,而又无需暴露该对象的内部表示。
4、分离集合对象的遍历行为到一个独立的迭代器类中。
符合的设计原则:
1、单一职责原则(Single Responsibility Principle)
迭代器模式将集合对象的遍历行为抽象到迭代器类中,集合类只负责存储,迭代器类只负责遍历。二者职责区分明确,符合单一职责原则。
2、开闭原则(Open Closed Principle)
可以在不修改集合类的情况下,定义新的迭代器类,满足扩展需求。增强了系统的可扩展性。
3、依赖倒转原则(Dependency Inversion Principle)
迭代器模式中,集合类和客户端都依赖于抽象迭代器接口,而不是依赖于具体迭代器类,倒转了依赖关系。
4、组合复用原则(Composite Reuse Principle)
客户端可以统一使用迭代器接口遍历不同的集合类,复用迭代器提供的遍历功能。
5、里氏替换原则(Liskov Substitution Principle)
迭代器模式中,每个迭代器类都可以通过继承迭代器接口,替换基类迭代器角色。