迭代器模式
为什么会出现迭代器模式?
程序设计中,我们经常需要访问聚合对象中的各个元素,比如链表的遍历,我们通常的做法是将链表的创建与遍历放在一个类中,但是这种方式不利于扩展,修改遍历算法就要修改源码,违反了开闭原则。但是如果让用户自己实现遍历的话,不仅会暴露聚合对象的内部表示,还会增加用户的负担,为了解决以上问题,出现了迭代器模式。迭代器模式是指在客户访问类与聚合类之间插入一个迭代器,这样就分离了聚合对象和其遍历,同时也不会暴露聚合对象的内部细节。
什么是迭代器模式?
定义: 提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。迭代器模式是一种对象行为型模式。
优点:
- 可以实现访问聚合对象的内容而无需暴露它的内部表示。
- 支持不同的遍历方式,可以自定义迭代器的子类实现新的遍历方式。
- 遵守单一职责原则和开闭原则。
- 封装性好,为遍历不同的聚合结构提供了一个统一的接口。
- 开发中几乎不需要自定义迭代器,开源框架提供的API一般足够用。
模式的结构与实现
迭代器模式是通过将聚合对象的遍历行为分离出来,抽象成迭代器类来实现的,其目的是在不暴露聚合对象的内部结构的情况下,让外部代码透明地访问聚合的内部数据。
结构
角色
- 抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
- 具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
- 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
- 具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
实现
使用迭代器遍历教室中的学生。
package com.pattern.Iterator;
/**
* @author wlj
* @Classname Aggregate
* @Description 聚合接口
* @Date 7/25/2022 10:50 AM
*/
public interface Aggregate {
// 添加聚合对象
void addAggregate(Object obj);
// 删除聚合对象
void deleteAggregate(Object obj);
// 获取迭代器
Iterator getIterator();
}
package com.pattern.Iterator;
import java.util.ArrayList;
/**
* @author wlj
* @Classname ConcreteAggregate
* @Description 具体的聚合对象(ConcreteAggregate)
* @Date 7/25/2022 10:58 AM
*/
public class ConcreteAggregate implements Aggregate{
ArrayList<Object> arrayList = new ArrayList<Object>();
@Override
public void addAggregate(Object obj) {
arrayList.add(obj);
}
@Override
public void deleteAggregate(Object obj) {
arrayList.remove(obj);
}
@Override
public Iterator getIterator() {
return new ConcreteIterator(arrayList);
}
}
package com.pattern.Iterator;
/**
* @author wlj
* @Classname Iterator
* @Description 迭代器接口
* @Date 7/25/2022 10:55 AM
*/
public interface Iterator {
// first
Object first();
// next
Object next();
// hasNext
boolean hasNext();
}
package com.pattern.Iterator;
import java.util.ArrayList;
/**
* @author wlj
* @Classname ClassroomIterator
* @Description 具体的迭代器
* @Date 7/25/2022 11:04 AM
*/
public class ConcreteIterator implements Iterator{
private ArrayList<Object> list = null;
private int index = -1;
public ConcreteIterator(ArrayList<Object> list) {
this.list = list;
}
@Override
public Object first() {
index = 0;
Object object = list.get(index);
return object;
}
@Override
public Object next() {
Object object = null;
if(this.hasNext()){
object = list.get(++index);
}
return object;
}
@Override
public boolean hasNext() {
if (index < list.size() - 1) {
return true;
} else {
return false;
}
}
}
package com.pattern.Iterator;
/**
* @author wlj
* @Classname Student
* @Description 聚合对象学生
* @Date 7/25/2022 10:58 AM
*/
public class Student {
// student name
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 + '\'' +
'}';
}
}
package com.pattern.Iterator;
import java.util.ArrayList;
/**
* @author wlj
* @Classname Client
* @Description 测试
* @Date 7/25/2022 11:20 AM
*/
public class Client {
public static void main(String[] args) {
Aggregate classroom = new ConcreteAggregate();
classroom.addAggregate(new Student("小明"));
classroom.addAggregate(new Student("小红"));
classroom.addAggregate(new Student("小花"));
Iterator it = classroom.getIterator();
while (it.hasNext()) {
// index默认为-1,第一个元素为index=0
Object obj = it.next();
System.out.println(obj.toString());
}
Student first = (Student) it.first();
System.out.println(first.toString());
}
}
// 输出
Student{name='小明'}
Student{name='小红'}
Student{name='小花'}
Student{name='小明'}
应用
- Java 中的 Collection、List、Set、Map 等都包含了迭代器。jdk已经提供了迭代器,我们一般无需再去实现。