迭代器模式(Iterator)
迭代器模式(Iterator)
Iterator:
迭代器模式是一种行为设计模式,提供一种方法顺序访问一个集合中的各个元素,而又不暴露对象的底层表现形式。
/**
* 迭代器模式
*
* @author CAI
* @time 2020/11/16
*/
public class IteratorPattern {
public static void main(String[] args) {
CourseCollection courses = initCollection();
CourseIterator all = courses.iterator(MajorType.ALL);
while (all.hasNext()) {
Course course = all.next();
System.out.println(course);
}
System.out.println();
System.out.println("<----------------------------->");
System.out.println();
CourseIterator cs = courses.iterator(MajorType.COMPUTER_SCIENCES);
while (cs.hasNext()) {
Course course = cs.next();
System.out.println(course);
}
}
private static CourseCollection initCollection() {
CourseCollection courses = new CourseCollectionImpl();
courses.add(new Course("计算机网络", MajorType.COMPUTER_SCIENCES));
courses.add(new Course("计算机操作系统", MajorType.COMPUTER_SCIENCES));
courses.add(new Course("计算机组成原理", MajorType.COMPUTER_SCIENCES));
courses.add(new Course("数据结构与算法", MajorType.COMPUTER_SCIENCES));
courses.add(new Course("生物化学", MajorType.BIOLOGY_SCIENCES));
courses.add(new Course("高等数学", MajorType.MATH));
courses.add(new Course("宏观经济学", MajorType.FINANCE));
courses.add(new Course("中国通史", MajorType.HISTORY));
return courses;
}
}
/**
* 专业类型枚举
*/
enum MajorType {
COMPUTER_SCIENCES("计算机科学与技术"),
BIOLOGY_SCIENCES("生物科学"),
MATH("数学"),
FINANCE("金融"),
HISTORY("历史"),
ALL("所有");
private String name;
MajorType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
/**
* 课程
*/
class Course {
/**
* 课程名
*/
private final String name;
/**
* 专业类型
*/
private final MajorType majorType;
public Course(String name, MajorType majorType) {
this.name = name;
this.majorType = majorType;
}
public String getName() {
return name;
}
public MajorType getMajorType() {
return majorType;
}
@Override
public String toString() {
return "Course{" +
"name='" + name + '\'' +
", majorType=" + majorType.getName() +
'}';
}
}
/**
* 课程集合接口
*/
interface CourseCollection {
/**
* 添加
*
* @param course 课程
*/
void add(Course course);
/**
* 删除
*
* @param course 课程
*/
void remove(Course course);
/**
* 遍历
*
* @param majorType 专业类型
* @return 课程迭代器
*/
CourseIterator iterator(MajorType majorType);
}
/**
* 课程迭代器接口
*/
interface CourseIterator {
/**
* 是否有下一个
*
* @return 存在下一个 : true
*/
Boolean hasNext();
/**
* 下一个
*
* @return 课程对象
*/
Course next();
}
/**
* 课程集合接口实现类
*/
class CourseCollectionImpl implements CourseCollection {
private final List<Course> courses;
public CourseCollectionImpl() {
courses = new ArrayList<>();
}
@Override
public void add(Course course) {
courses.add(course);
}
@Override
public void remove(Course course) {
courses.remove(course);
}
@Override
public CourseIterator iterator(MajorType majorType) {
return new CourserIteratorImpl(majorType, courses);
}
}
/**
* 课程迭代器接口实现类
*/
class CourserIteratorImpl implements CourseIterator {
private final MajorType majorType;
private final List<Course> courses;
private int position;
public CourserIteratorImpl(MajorType majorType, List<Course> courses) {
this.majorType = majorType;
this.courses = courses;
}
@Override
public Boolean hasNext() {
while (position < courses.size()) {
Course course = courses.get(position);
if (course.getMajorType().equals(majorType) || majorType.equals(MajorType.ALL)) {
return true;
} else {
position++;
}
}
return false;
}
@Override
public Course next() {
Course course = courses.get(position);
position++;
return course;
}
}
Iterator
(课程迭代器接口):声明遍历集合所需的操作。- 具体迭代器(课程迭代器实现类):实现遍历集合的特定算法,迭代器对象必须跟踪自身的遍历进度(使用
Position
记录)。这使得多个迭代器可以相互独立地遍历同一个集合。 Collection
(课程集合接口):声明一个或多个方法来获取与集合兼容的迭代器。返回的方法必须声明为迭代器接口,故:具体集合可以返回不同种类的迭代器。- 具体集合(课程集合实现类):当客户端调用迭代器方式时,返回一个具体的迭代器对象。
- 客户端:通过集合和迭代器的接口与两者进行交互。客户端无需与具体类相耦合,允许同一客户端代码使用不同的集合和迭代器。
- 客户端通常不会自行创建迭代器,而是直接从集合中获取。若客户端想要自定义迭代器时,才需要创建。
应用场景
- 当集合底层的数据结构较为复杂时,若希望对外部隐藏内部的复杂性时,可以使用迭代器模式。
- 封装复杂数据结构的交互细节,为客户端提供访问元素的简单方法。这样对调用者友好,且能避免调用者在直接与集合交互时执行错误的操作,起到保护类的作用,也提升了代码的稳定性。
- 希望集合有多种遍历方式时,可以使用迭代器模式。
- 项目中存在大量遍历代码时,可以考虑使用迭代器模式简化。
- 当业务逻辑中存在大量的遍历代码时,会让原有方法的职责变的模糊,降低可维护性;将遍历代码抽离到特定的迭代器中会让原有的方法更精炼,也更简洁。
- 若希望能遍历不同,甚至无法预知数据结构的集合时,可以使用迭代器模式。
- 迭代器提供了一组公共的接口用于集合对象的访问。
优缺点
- 优点:
- 分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明的访问集合内部的数据。满足单一职责的原则。
- 在原有代码的基础上,创建新的集合或迭代器时无需修改已有的代码;满足开闭原则。
- 可以并行遍历同一集合,每个迭代器对象都包含其自身的遍历状态。
- 可以暂停遍历过程,并在需要时恢复遍历。
- 缺点:
- 如果只是简单的遍历,迭代器会让原有的操作变的复杂。
- 对于特殊的集合,使用迭代器进行遍历效率可能无法保证。
在 Java 中的应用
以
Java
核心库为例:
java.util.Iterator
java.util.Scanner
java.util.Enumeration