迭代器模式

《大话设计模式》第20章读书笔记,介绍迭代器模式

Posted by GrayWind on November 19, 2018

迭代器模式(Iterator)提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑使用迭代器模式。另外,需要对聚集有多种方式遍历时,可以考虑使用迭代器模式。迭代器模式可以为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。

但是,因为目前Java等语言本身已经把这个模式做在语言中了,所以通常不需要自己去写迭代器模式。

iterator

Iterator迭代器抽象类

public interface Iterator {
	public Object first();
	public Object next();
	public boolean isDone();
	public Object currentItem();
}

Aggregate聚集抽象类

public interface Aggregate {
	public Iterator createIterator();
}

ConcreteIterator具体迭代器类,实现Iterator

public class ConcreteIterator implements Iterator {
	//定义了一个具体聚集对象
	private ConcreteAggregate aggregate;
	private int current = 0;
	
	public ConcreteIterator(ConcreteAggregate aggregate) {
		this.aggregate = aggregate;
	}
	
	@Override
	//得到聚集的第一个对象
	public Object first() {
		return aggregate.get(0);
	}

	@Override
	//得到聚集的下一个对象
	public Object next() {
		Object ret = null;
		current++;
		if(current < aggregate.count()) {
			ret = aggregate.get(current);
		}
		return ret;
	}

	@Override
	//判断是否遍历到结尾,是的话返回true
	public boolean isDone() {
		return current >= aggregate.count();
	}

	@Override
	//返回当前对象
	public Object currentItem() {
		return aggregate.get(current);
	}

}

ConcreteAggregate具体聚集类,实现Aggregate

public class ConcreteAggregate implements Aggregate {
	//声明一个List,用于存放聚合对象
	private List<Object> items = new ArrayList<>();
	
	@Override
	public Iterator createIterator() {
		return new ConcreteIterator(this);
	}
	//返回聚集总个数
	public int count() {
		return items.size();
	}
	
	public Object get(int index) {
		return items.get(index);
	}
	
	public void set(int index, Object value) {
		if(index < items.size()) {
			items.set(index, value);
		}else {
			items.add(value);
		}
	}

}

客户端代码

public class Test {
	public static void main(String[] args) {
		ConcreteAggregate a = new ConcreteAggregate();

        a.set(0, "大鸟");
        a.set(1, "小菜");
        a.set(2, "行李");
        a.set(3, "老外");
        a.set(4, "公交内部员工");
        a.set(5, "小偷");

        Iterator i = new ConcreteIterator(a);
        while (!i.isDone())
        {
            System.out.println(i.currentItem().toString() + " 请买车票!");
            i.next();
        }
	}
}

运行结果

大鸟 请买车票!
小菜 请买车票!
行李 请买车票!
老外 请买车票!
公交内部员工 请买车票!
小偷 请买车票!

Java中的Iterator接口,一共有4个方法,所以它只能从前往后遍历,并且每个元素只能遍历一次。forEachRemaining是JDK1.8新增的流式操作方法。

public interface Iterator<E> {
    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}