迭代器模式
迭代器模式(Iterator Pattern)提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。这种类型的设计模式属于行为型模式。
迭代器模式解决的问题
对于不同类型的集合,使用同一种方式进行遍历,客户端不需要关心服务端的内部实现方式。
迭代器模式模式角色
抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
使用场景
需要为聚合对象提供多种遍历方式时。
需要为遍历不同的聚合结构提供一个统一的接口时。
访问一个聚合对象的内容而无须暴露其内部细节的表示。
迭代器方法类型
hasNext方法:是否还存在元素
next方法:下一个元素对象
代码实现
打印各班级的名单,1班老师用的是数组存储,2班老师用的是List
/**
* 打印各班级的名单,1班老师用的是数组存储,2班老师用的是List
*/
public class BadCode {
private String class1[] = {"java程序员思维", "java", "设计模式", "迭代器模式"};
private List<String> class2 = Arrays.asList(class1);
private void printAllName() {
//打印1班的学生姓名
System.out.println("1班学生姓名");
for (String name : class1) {
System.out.println(name);
}
System.out.println("-----------------");
System.out.println("2班学生姓名");
//打印2班的学生姓名
for (String name : class2) {
System.out.println(name);
}
}
public static void main(String[] args) {
BadCode badCode = new BadCode();
badCode.printAllName();
}
}
运行结果:
上面的代码是一个比较糟糕的实现,客户端明确的直到了服务端的具体实现,还有一个问题是如果有一个新的班级,老师用的是HashMap来存储,客户端的代码需要被重新修改,不支持开闭原则,我们对以上的代码进行改进。
/**
* 迭代器
*/
public interface Iterator {
public boolean hasNext();
public Object next();
}
//数组存储
public class NameArrayIterator implements Iterator {
public String names[] = {"java程序员思维", "java", "设计模式", "迭代器模式"};
private int index = 0;
public boolean hasNext() {
if (index < names.length) {
return true;
}
return false;
}
public Object next() {
if (this.hasNext()) {
return names[index++];
}
return null;
}
}
//list存储
public class NameListIterator implements Iterator {
private List<String> arrayList;
private int index = 0;
public NameListIterator() {
arrayList = new ArrayList<String>();
arrayList.add("java程序员思维");
arrayList.add("java");
arrayList.add("设计模式");
arrayList.add("迭代器模式");
}
public boolean hasNext() {
if(index < arrayList.size()){
return true;
}
return false;
}
public Object next() {
Object object = arrayList.get(index);
index++;
return object;
}
}
public class Client {
private Iterator iterator;
public Client(Iterator iterator) {
this.iterator = iterator;
}
public void printName(){
while (iterator.hasNext()){
System.out.println(iterator.next().toString());
}
}
public Iterator getIterator() {
return iterator;
}
public void setIterator(Iterator iterator) {
this.iterator = iterator;
}
}
public class IteratorPatternTest {
public static void main(String[] args) {
NameArrayIterator nameArrayIterator = new NameArrayIterator();
Client client = new Client(nameArrayIterator);
System.out.println("使用数组存储" );
client.printName();
System.out.println("----------------------------");
NameListIterator nameListIterator = new NameListIterator();
client.setIterator(nameListIterator);
System.out.println("使用List存储" );
client.printName();
}
}
使用迭代器模式,隐藏了服务端的代码实现,同时使用了策略模式,当有新的实现,也满足开闭原则,不需要修改客户端代码。
运行结果:
JDK和框架中的迭代器模式
public Iterator<E> iterator() {
return new ArrayList.Itr();
}
public Iterator<E> iterator() {
return this.map.keySet().iterator();
}
jdk中的java.util包下的Iterator,使用的就是迭代器模式,ArrayList、HashSet等都提供了iterator方法,获取迭代器。
优缺点
优点:隐藏了聚合对象的内部实现,提供统一的方式遍历聚合对象。
缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
生活中的命令模式
迭代器有点像平台,定义的统一的入口,所有的商家都按照平台的规则,每个商家都有自己的店铺页,用户可以在商家店铺中,浏览商家的所有商品。天猫、京东、美团、饿了么等等,微信小程序,也提供了一个迭代器,能方便用户找到对应商家的应用服务,无需下载相应的app,打开即用。
我的启发
迭代器模式,提供一套标准,让用户无需关心具体的实现细节,用统一的方式给用户提供最便捷的服务,用户填好自己的收货地址、下完单付完款,就可以坐等第二天收快递,以至于商家发什么快递,顺丰、圆通、中通,用户并没有那么关心。顾客是上帝,请给我提供最简单,最省心的服务。
设计模式系列文章历史
Head First 设计模式之装饰器模式,因为参与,所以认同