作用:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示,当你需要对聚集有多种方式遍历时,可以考虑用迭代器模式,为遍历不同聚集结构提供如开始,下一个,是否结束,当前那一项等统一接口。
迭代器模式:就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。
1、迭代器模式
1、聚集抽象类
abstract class Aggregate{
//创建迭代器
public abstract Iterator createIterator();
}
2、聚集类实现类
//具体聚集类,继承Aggregate
class ConcreteAggregate extends Aggregate{
//声明一个ArrayList泛型变量,用于存放聚合对象
private ArrayList<Object> items = new ArrayList<Object>();
public Iterator createIterator(){
return new ConcreteIterator(this);
}
//返回聚集总个数
public int getCount(){
return items.size();
}
//增加新对象
public void add(Object object){
items.add(object);
}
//得到指定索引对象
public Object getCurrentItem(int index){
return items.get(index);
}
}
3、迭代器抽象类
abstract class Iterator{
public abstract Object first(); //第一个
public abstract Object next(); //下一个
public abstract boolean isDone(); //是否到最后
public abstract Object currentItem(); //当前对象
}
4、迭代器实现类
//具体迭代器类,继承Iterator
class ConcreteIterator extends Iterator{
private ConcreteAggregate aggregate;
private int current = 0;
//初始化时将具体的聚集对象传入
public ConcreteIterator(ConcreteAggregate aggregate){
this.aggregate = aggregate;
}
//得到第一个对象
public Object first(){
return aggregate.getCurrentItem(0);
}
//得到下一个对象
public Object next() {
Object ret = null;
current++;
if (current < aggregate.getCount()) {
ret = aggregate.getCurrentItem(current);
}
return ret;
}
//判断当前是否遍历到结尾,到结尾返回true
public boolean isDone(){
return current >= aggregate.getCount() ? true : false;
}
//返回当前的聚集对象
public Object currentItem(){
return aggregate.getCurrentItem(current);
}
}
5、迭代器实现类(倒序方式)
//具体迭代器类(倒序),继承Iterator
class ConcreteIteratorDesc extends Iterator{
private ConcreteAggregate aggregate;
private int current = 0;
public ConcreteIteratorDesc(ConcreteAggregate aggregate){
this.aggregate = aggregate;
current = aggregate.getCount()-1;
}
//第一个对象
public Object first(){
return aggregate.getCurrentItem(aggregate.getCount()-1);
}
//下一个对象
public Object next() {
Object ret = null;
current--;
if (current >= 0) {
ret = aggregate.getCurrentItem(current);
}
return ret;
}
//判断当前是否遍历到结尾,到结尾返回true
public boolean isDone(){
return current <0 ? true : false;
}
//返回当前的聚集对象
public Object currentItem(){
return aggregate.getCurrentItem(current);
}
}
6、测试和结果
public class Test {
public static void main(String[] args){
System.out.println("**********************************************");
System.out.println("《大话设计模式》代码样例");
System.out.println();
ConcreteAggregate bus = new ConcreteAggregate();
bus.add("大鸟");
bus.add("小菜");
bus.add("行李");
bus.add("老外");
bus.add("公交内部员工");
bus.add("小偷");
//正序迭代器
//Iterator conductor = new ConcreteIterator(bus);
//倒序迭代器
Iterator conductor = new ConcreteIteratorDesc(bus);
conductor.first();
while (!conductor.isDone()) {
System.out.println(conductor.currentItem() + ",请买车票!");
conductor.next();
}
System.out.println();
System.out.println("**********************************************");
}
}
结果
2、迭代器的使用
1、代码
java中遍历集合的迭代器,就是这种设计模式
public class Test {
public static void main(String[] args){
System.out.println("**********************************************");
System.out.println("《大话设计模式》代码样例");
System.out.println();
ArrayList<String> bus = new ArrayList<String>();
bus.add("大鸟");
bus.add("小菜");
bus.add("行李");
bus.add("老外");
bus.add("公交内部员工");
bus.add("小偷");
System.out.println("foreach遍历:");
for(String item : bus){
System.out.println(item + ",请买车票!");
}
System.out.println();
System.out.println("Iterator遍历:");
Iterator<String> conductor = bus.iterator();
while (conductor.hasNext()) {
System.out.println(conductor.next() + ",请买车票!");
}
System.out.println();
System.out.println("ListIterator逆向遍历:");
ListIterator<String> conductorDesc = bus.listIterator(bus.size());
while (conductorDesc.hasPrevious()) {
System.out.println(conductorDesc.previous() + ",请买车票!");
}
System.out.println();
System.out.println("**********************************************");
}
}
2、源码
Iterator:
public interface Iterator<E> {
/**
* Returns {@code true} if the iteration has more elements.
* (In other words, returns {@code true} if {@link #next} would
* return an element rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
boolean hasNext();
/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
E next();
/**
* Removes from the underlying collection the last element returned
* by this iterator (optional operation). This method can be called
* only once per call to {@link #next}.
* <p>
* The behavior of an iterator is unspecified if the underlying collection
* is modified while the iteration is in progress in any way other than by
* calling this method, unless an overriding class has specified a
* concurrent modification policy.
* <p>
* The behavior of an iterator is unspecified if this method is called
* after a call to the {@link #forEachRemaining forEachRemaining} method.
*
* @implSpec
* The default implementation throws an instance of
* {@link UnsupportedOperationException} and performs no other action.
*
* @throws UnsupportedOperationException if the {@code remove}
* operation is not supported by this iterator
*
* @throws IllegalStateException if the {@code next} method has not
* yet been called, or the {@code remove} method has already
* been called after the last call to the {@code next}
* method
*/
default void remove() {
throw new UnsupportedOperationException("remove");
}
/**
* Performs the given action for each remaining element until all elements
* have been processed or the action throws an exception. Actions are
* performed in the order of iteration, if that order is specified.
* Exceptions thrown by the action are relayed to the caller.
* <p>
* The behavior of an iterator is unspecified if the action modifies the
* collection in any way (even by calling the {@link #remove remove} method
* or other mutator methods of {@code Iterator} subtypes),
* unless an overriding class has specified a concurrent modification policy.
* <p>
* Subsequent behavior of an iterator is unspecified if the action throws an
* exception.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* while (hasNext())
* action.accept(next());
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @since 1.8
*/
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
ListIterator:
public interface ListIterator<E> extends Iterator<E> {
// Query Operations
/**
* Returns {@code true} if this list iterator has more elements when
* traversing the list in the forward direction. (In other words,
* returns {@code true} if {@link #next} would return an element rather
* than throwing an exception.)
*
* @return {@code true} if the list iterator has more elements when
* traversing the list in the forward direction
*/
boolean hasNext();
/**
* Returns the next element in the list and advances the cursor position.
* This method may be called repeatedly to iterate through the list,
* or intermixed with calls to {@link #previous} to go back and forth.
* (Note that alternating calls to {@code next} and {@code previous}
* will return the same element repeatedly.)
*
* @return the next element in the list
* @throws NoSuchElementException if the iteration has no next element
*/
E next();
/**
* Returns {@code true} if this list iterator has more elements when
* traversing the list in the reverse direction. (In other words,
* returns {@code true} if {@link #previous} would return an element
* rather than throwing an exception.)
*
* @return {@code true} if the list iterator has more elements when
* traversing the list in the reverse direction
*/
boolean hasPrevious();
/**
* Returns the previous element in the list and moves the cursor
* position backwards. This method may be called repeatedly to
* iterate through the list backwards, or intermixed with calls to
* {@link #next} to go back and forth. (Note that alternating calls
* to {@code next} and {@code previous} will return the same
* element repeatedly.)
*
* @return the previous element in the list
* @throws NoSuchElementException if the iteration has no previous
* element
*/
E previous();
/**
* Returns the index of the element that would be returned by a
* subsequent call to {@link #next}. (Returns list size if the list
* iterator is at the end of the list.)
*
* @return the index of the element that would be returned by a
* subsequent call to {@code next}, or list size if the list
* iterator is at the end of the list
*/
int nextIndex();
/**
* Returns the index of the element that would be returned by a
* subsequent call to {@link #previous}. (Returns -1 if the list
* iterator is at the beginning of the list.)
*
* @return the index of the element that would be returned by a
* subsequent call to {@code previous}, or -1 if the list
* iterator is at the beginning of the list
*/
int previousIndex();
// Modification Operations
/**
* Removes from the list the last element that was returned by {@link
* #next} or {@link #previous} (optional operation). This call can
* only be made once per call to {@code next} or {@code previous}.
* It can be made only if {@link #add} has not been
* called after the last call to {@code next} or {@code previous}.
*
* @throws UnsupportedOperationException if the {@code remove}
* operation is not supported by this list iterator
* @throws IllegalStateException if neither {@code next} nor
* {@code previous} have been called, or {@code remove} or
* {@code add} have been called after the last call to
* {@code next} or {@code previous}
*/
void remove();
/**
* Replaces the last element returned by {@link #next} or
* {@link #previous} with the specified element (optional operation).
* This call can be made only if neither {@link #remove} nor {@link
* #add} have been called after the last call to {@code next} or
* {@code previous}.
*
* @param e the element with which to replace the last element returned by
* {@code next} or {@code previous}
* @throws UnsupportedOperationException if the {@code set} operation
* is not supported by this list iterator
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this list
* @throws IllegalArgumentException if some aspect of the specified
* element prevents it from being added to this list
* @throws IllegalStateException if neither {@code next} nor
* {@code previous} have been called, or {@code remove} or
* {@code add} have been called after the last call to
* {@code next} or {@code previous}
*/
void set(E e);
/**
* Inserts the specified element into the list (optional operation).
* The element is inserted immediately before the element that
* would be returned by {@link #next}, if any, and after the element
* that would be returned by {@link #previous}, if any. (If the
* list contains no elements, the new element becomes the sole element
* on the list.) The new element is inserted before the implicit
* cursor: a subsequent call to {@code next} would be unaffected, and a
* subsequent call to {@code previous} would return the new element.
* (This call increases by one the value that would be returned by a
* call to {@code nextIndex} or {@code previousIndex}.)
*
* @param e the element to insert
* @throws UnsupportedOperationException if the {@code add} method is
* not supported by this list iterator
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this list
* @throws IllegalArgumentException if some aspect of this element
* prevents it from being added to this list
*/
void add(E e);
}