1.概述
迭代器模式可以顺序访问一个容器对象中各个元素,而又不需要暴露该容器对象的内部细节。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。每一个聚集对象都可以有一个或一个以上的迭代器对象,每一个迭代器的迭代状态可以是彼此对立。
相似情景:
1.假设一种场景,家兴买了一个行李箱和一个储物箱,家兴的妈妈帮家兴收拾好行李了,都放在这两个箱子里面,但是由于某种情况,家兴想知道这两个箱子的东西存放顺序和所放的东西。由于这两个箱子里面的结构不同,要想知道这些东西就必须分别打开进行查看才能达到目的。那么存在这样的解决方案,通过迭代器可以不用打开一个个进行查看就可以知道。
2.实际场景,一个对象序列和一个对象数组,如果想遍历查看序列和数组,序列就必须使用ArrayList的get(i),size()方法,数组需要length和中括号,如果使用迭代器我们只需要创建一个对象,再通过使用迭代器里面的hasNext(),next()就可以达到这样目的,我们不需要知道它里面的内部结构,只需要它是一个集合就行了。
2)解决方案和使用场景
当你需要访问一个聚集的对象,而且不管这些对象是什么都需要遍历的时候,你就要考虑到迭代器模式;当聚集有多种方式遍历时候,可以考虑迭代器模式;迭代器模式为遍历不同的聚集结构提供开始、下一个,是否结束,当前哪一项等统一接口。迭代器的相关接口一般有Iterator和IEnumerable;
3)结构
Iterator:抽象迭代器。迭代器定义访问和遍历元素的接口。
ArrayIterator:数组迭代器。实现迭代器接口,在遍历是跟踪当前聚合对象的位置。
ListIterator:序列迭代器。实现迭代器接口,在遍历是跟踪当前聚合对象的位置。
Aggregate:抽象聚合类。定义一个创建迭代器对象类。
ArrayAggregate:数组聚合类。实现创建迭代器对象,返回一个具体数组迭代器的实例。
ListAggregate:序列聚合类。实现创建迭代器对象,返回一个具体序列迭代器的实例。
4)迭代器模式XML图
5)代码实现
//聚合抽象类
public abstract class Arggregate {
public abstract Iterator createIterator();
}
//数组聚合类
public class ArrayArggregate extends Arggregate{
private Object[] ob;
public ArrayArggregate(Object[] ob){
this.ob = ob;
}
@Override
public Iterator createIterator() {
// TODO Auto-generated method stub
return new ArrayIterator(this);
}
public int size(){
return ob.length;
}
public Object[] elements(){
return ob;
}
}
//序列聚合类
public class ListArggregate extends Arggregate{
private ArrayList<Object> list;
public ListArggregate(ArrayList<Object> list){
this.list = list;
}
@Override
public Iterator createIterator() {
// TODO Auto-generated method stub
return new ListIterator(this);
}
public int size(){
return list.size();
}
public ArrayList<Object> elements(){
return list;
}
}
//迭代器
public interface Iterator {
public Object first();
public boolean hasNext();
public Object next();
public Object all();
public boolean remove(int i);
}
//数组迭代器
import java.util.Arrays;
public class ArrayIterator implements Iterator{
private ArrayArggregate arrayArggregate;
private int size;
private int index = 0;
private Object[] objects;
public ArrayIterator(ArrayArggregate arrayArggregate){
this.arrayArggregate = arrayArggregate;
this.size = arrayArggregate.size();
this.objects = arrayArggregate.elements();
}
@Override
public Object first() {
// TODO Auto-generated method stub
if(objects[0]==null){
return null;
}
return objects[0];
}
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
if(objects[index+1]!=null){
return true;
}
return false;
}
@Override
public Object next() {
// TODO Auto-generated method stub
index+=1;
if(objects[index]==null){
return null;
}
return objects[index];
}
@Override
public String all() {
// TODO Auto-generated method stub
return Arrays.toString(objects);
}
@Override
public boolean remove(int i) {
// TODO Auto-generated method stub
if(i<=0){
throw new IllegalStateException
("You can't remove an item until you've done at least one next()");
}
if(objects[i-1]!=null){
for(int j = i-1;j<size-1;j++){
objects[j]= objects[j+1];
}
size--;
objects[size-1]=null;
}
return true;
}
}
//序列迭代类
import java.util.ArrayList;
public class ListIterator implements Iterator{
private ListArggregate list;
private int size;
private int index = 0;
private ArrayList<Object> lists;
public ListIterator(ListArggregate list){
this.list = list;
size = list.size();
lists = list.elements();
}
@Override
public Object first() {
// TODO Auto-generated method stub
if(lists.get(0)==null){
return null;
}
return lists.get(0);
}
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
if(lists.get(index+1)==null){
return false;
}
return true;
}
@Override
public Object next() {
// TODO Auto-generated method stub
index+=1;
if(lists.get(index)==null){
return null;
}
return lists.get(index);
}
@Override
public Object all() {
// TODO Auto-generated method stub
return lists;
}
@Override
public boolean remove(int i) {
// TODO Auto-generated method stub
if(i<=size){
lists.remove(i);
return true;
}
return false;
}
}
//客户端
import java.util.ArrayList;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//数组迭代器
String[] prams = {"yatming","juddy","john","amy"};
Arggregate argg = new ArrayArggregate(prams);
Iterator it1 = argg.createIterator();
System.out.println(it1.first());
if(it1.hasNext()){
System.out.println(it1.next());
}
System.out.println(it1.all());
//
ArrayList<Object> List = new ArrayList<Object>();
List.add("家兴");
List.add(1);
List.add("家敏");
Arggregate argg1 = new ListArggregate(List);
Iterator it2 = argg1.createIterator();
it2.first();
if(it2.hasNext()){
System.out.println(it1.next());
}
it2.remove(2);
System.out.println(it2.all());
}
}
程序运行结果
yatming
juddy
[yatming, juddy, john, amy]
john
[家兴, 1]
6)结果分析
1.聚合的数据已经被封装起来了,客户端不知道里面的逻辑,符合单一职责原则,提高后期的扩展性。
2.只要实现迭代器,我们就可以使用迭代器查询里面的方法,包括删除等行为。
3.共同实现一个迭代器接口,可以实现多个具体类。
7)迭代器模式缺点
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
8)与其它模式
1. 工厂方法模式
多态迭代器靠Factory Method来例化适当的迭代器子类。
2.组合模式:通常与组合模式一起使用,将存储数据和遍历数据一起分离,避免子类爆炸式增长
3.备忘录模式:常与迭代器模式一起使用。迭代器可使用一个 Memento来捕获一个迭代的状态。迭代器在其内部存储Memento。