设计模式系列之迭代器模式【十】

1. 定义

提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

Iterator模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访问集合内部的数据。

2. 角色组成

  1. 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素;
  2. 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。
  3. 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。
  4. 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。

3. 示例

3.1 迭代器角色

public interface Iterator {
	public Object next(); 
	public boolean hasNext();
}

3.2 具体迭代器角色

public class ConcreteIterator implements Iterator {

    private List list = new ArrayList();
    private int cursor = 0;

    public ConcreteIterator(List list) {
        this.list = list;
    }

    @Override
    public Object next() {
        Object obj = null;
        if (this.hasNext()) {
            obj = this.list.get(cursor++);
        }
        return obj;
    }

    @Override
    public boolean hasNext() {
        if (cursor == list.size()) {
            return false;
        }
        return true;
    }
}

3.3 容器角色

public interface Aggregate {
    public void add(Object obj);  
    public void remove(Object obj);  
    public Iterator iterator(); 
}

3.4 具体容器角色

public class ConcreteAggregate implements Aggregate {

    private List list = new ArrayList();  
    
    @Override
    public void add(Object obj) {
        list.add(obj);
    }
    @Override
    public void remove(Object obj) {
        list.remove(obj);
    }
    @Override
    public Iterator iterator() {
         return new ConcreteIterator(list); 
    }
}

4. 测试

public class Client {

    public static void main(String[] args) {
        Aggregate ag = new ConcreteAggregate();
        ag.add("小明");
        ag.add("小红");
        ag.add("小刚");
        Iterator it = ag.iterator();
        while (it.hasNext()) {
            String str = (String) it.next();
            System.out.println(str);
        }
    }
}

执行结果:

小明
小红
小刚

6. 优点和缺点

6.1 优点

  1. 它支持以不同的方式遍历一个聚合对象
  2. 迭代器简化了聚合类
  3. 在同一个聚合上可以有多个遍历
  4. 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码

6.2 缺点

由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性

7. JDK相关

在jdk中,与迭代器相关的接口有两个:Iterator 与 Iterable。

  1. Iterator:迭代器,Iterator及其子类通常是迭代器本身的结构与方法;迭代器是一种模式,它可以使得对于序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的。只要拿到这个对象,使用迭代器就可以遍历这个对象的内部。
  2. Iterable:可迭代的,那些想用到迭代器功能的其它类,如AbstractList HashMap等,需要实现该接口。

7.1 Iterator

Iterator接口实现后的功能是“使用”一个迭代器。

Package  java.util;   
public interface Iterator<E> {  
 //判断是否存在下一个对象元素  
   boolean hasNext();
 //获得下一个元素
   E next();  
  //移除下一个元素
   void remove();  
} 

7.2 Iterable

实现Iterable接口后的功能是“返回”一个迭代器(Iterator),我们常用的实现了该接口的子接口有: Collection, Deque, List, Queue, Set 等.该接口的iterator()方法返回一个标准的Iterator实现。

public interface Iterable<T> {    
   Iterator<T> iterator();    
} 

7.3 迭代器的实现

  1. 若类A想要使用迭代器,则它的类声明部分为 class A implement Iterable
  2. 在类A实现中,要实现Iterable接口中的唯一方法:Iterator iterator(); 这个方法用于返回一个迭代器,即Iterator接口及其子类;
  3. 在类A中,定义一个内部类S,专门用于实现Iterator接口,定制类A自已的迭代器实现。
    //A实现Iterable接口
class A implement Iterable    
{    
   //该接口返回一个Iterator对象
    Iterator<T> iterator() {...}    
    class S implement Iterator<E>{    
    //上面这个对象会有具体实现的方法
        boolean hasNext() {....}    
        E next() {....}    
        void remove() {....}    
    }    
}

抽象类AbstractList的jdk源码:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { // List接口实现了Collection, Iterable   
   
   protected AbstractList() {    
   }    
     
   ...    
   // 这里返回一个迭代器对象  
   public Iterator<E> iterator() {    
   		return new Itr();   
   }    
    
    //  Itr内部类实现迭代器  
    private class Itr implements Iterator<E> { 
         
	    int cursor = 0;    
	    int lastRet = -1;    
	    int expectedModCount = modCount;    
	
	    // 实现hasNext方法  
	    public boolean hasNext() {  
	            return cursor != size();    
	    }    
	     // 实现next方法  
	    public E next() { 
	           //判断是否有下一个
	            checkForComodification();    
	        try {    
	        E next = get(cursor);    
	        lastRet = cursor++;   
	        //返回下一个 
	        return next;    
	        } catch (IndexOutOfBoundsException e) {    
	        checkForComodification();    
	        throw new NoSuchElementException();    
	        }    
	    }    
	    // 实现remove方法  
	    public void remove() {  
	        if (lastRet == -1)    
	        throw new IllegalStateException();    
	            checkForComodification();    
	    
	        try {    
	        AbstractList.this.remove(lastRet);    
	        if (lastRet < cursor)    
	            cursor--;    
	        lastRet = -1;    
	        expectedModCount = modCount;    
	        } catch (IndexOutOfBoundsException e) {    
	        throw new ConcurrentModificationException();    
	        }    
	    }    
	    //判断是否有下一个方法
	    final void checkForComodification() {    
	        if (modCount != expectedModCount)    
	        throw new ConcurrentModificationException();    
	    }    
    }    
} 

你可能感兴趣的:(java,设计模式)