Java设计模式笔记之迭代器模式

来源:互联网 发布:rs485网络接口引脚图 编辑:程序博客网 时间:2024/05/16 13:03

1.迭代器模式

迭代器(子)模式(Iterator)又叫游标模式,是对象的行为模式。迭代器模式可以顺序的访问一个聚集中的元素,而不用暴露聚集的内部表象

2.为什么需要迭代器模式

一个聚集持有多个对象,就需要对客户端提供遍历对象的方法,使用过程可能会出现以下问题:

(1)迭代逻辑没有改变,但是需要将一种聚集换成另一种聚集。

(2)聚集没有改变,但是迭代方式需要改变,例如新增可以删除元素的功能。

出现这些问题,就需要修改客户端代码或者修改聚集的方法。这是因为聚集对象和迭代逻辑耦合过紧,需要新增迭代子对象,将迭代逻辑封装到里面,从而与聚集本身分开

不同的聚集可以提供相同的迭代器对象,从而使客户端无需知道知道聚集的底层结构。

一个聚集可以提供多个不同的迭代对象,从而使得遍历逻辑的变化不会影响到聚集本身

3.迭代器模式结构

迭代器模式的一般结构图如下:


  • Iterator:抽象迭代器,定义遍历元素所需的所有接口
  • ConcreteIterator:具体迭代器,实现Iterator的所有接口,并保持迭代过程中的游标位置。
  • Aggregate:聚集角色,提供聚集接口和创建迭代器的接口。
  • ConcreteAggregate:具体聚集角色,持有元素对象,并实现创建具体迭代器对象的接口。
  • Client:客户端,持有聚集及其迭代器对象的引用,使用迭代器对象访问或者操作聚集中的元素。

4.迭代器的两种实现方式

(1)白箱聚集和外禀迭代子

聚集对外界透明,提供访问自己元素的接口,迭代子只保持一个迭代的游标位置,并通过聚集的接口访问其中的元素。
示例代码:
Aggregate.java(抽象聚集)
package com.patterns.iterator.whitebox;abstract public class Aggregate{    public Iterator createIterator()    {        return null;    }}

ConcreteAggregate.java(具体聚集)
package com.patterns.iterator.whitebox;public class ConcreteAggregate extends Aggregate{/** * 为简单起见,初始化一个数组 */    private Object objs[]= {"Monk Tang",        "Monkey", "Pigsy",        "Sandy", "Horse"};    /**     * 实现创建迭代器的方法     */    public Iterator createIterator()    {        return new ConcreteIterator(this);    }        /**     * 对外透明访问持有元素的方法,迭代子通过次方法遍历     * @param index     * @return     */    public Object getElement(int index)    {if (index < objs.length)        {return objs[index];        }        else        {            return null;        }    }    public int size()    {return objs.length;    }}

Iterator.java(抽象迭代器)
public interface Iterator{    void first();    void next();    boolean isDone();    Object currentItem();}

ConcreteIterator.java(具体迭代器)
public class ConcreteIterator implements Iterator{       private ConcreteAggregate agg;    //迭代游标private int index = 0;    private int size = 0;    public ConcreteIterator(ConcreteAggregate agg)    {this.agg = agg;        size = agg.size();        index = 0 ;    }    public void first()    {index = 0 ;    }    public void next()    {if (index < size)        {index++;        }    }    public boolean isDone()    {        return (index >= size);    }    public Object currentItem()    {        return agg.getElement(index);    }}

Client.java(客户端)
public class Client{   //迭代器对象    private Iterator it;        //聚集对象    private Aggregate agg = new ConcreteAggregate();    public void operation()    {        it = agg.createIterator();        while( !it.isDone() )        {System.out.println(it.currentItem().toString());            it.next();        }    }    public static void main(String[] args)    {        Client client = new Client();client.operation();    }}

聚集提供了遍历放,但是迭代器将迭代过程抽象化,使得客户端和迭代逻辑分开。在聚集发生变化时,避免修改客户端;在迭代方法发生变化时,避免修改聚集本身。
如果系统需要对不同聚集进行迭代。为每个聚集实现一个具体迭代器,可以让系统使用统一的迭代接口进行遍历。

(2)黑箱聚集与内禀迭代器

黑箱聚集不向外部提供遍历自己元素对象的接口,为了是迭代器访问聚集的元素,需要把迭代器实现成聚集的内部类(内禀迭代器)。
这种迭代器的实现和(1)白箱聚集和外禀迭代子  的实现不同在于聚集的实现和具体迭代器的实现,其他代码与(1)中一样

ConcreteAggregate.java
package com.patterns.iterator.blackbox;/** * 不向外提供访问内部元素的方法 * @author chenxh * */public class ConcreteAggregate extends Aggregate{/** * 内部元素 */    private Object[] objs = {"Monk Tang",        "Monkey", "Pigsy",        "Sandy", "Horse"};    /**     * 创建迭代器     */    public Iterator createIterator()    {        return new ConcreteIterator();    }    /**     * 聚集内部类实现的迭代器,可以访问外部类的私有属性和方法     * @author chenxh     *     */private class ConcreteIterator        implements Iterator{//游标private int currentIndex = 0;public void first()        {currentIndex = 0;        }public void next()        {            if ( currentIndex < objs.length )            {currentIndex++;            }        }public boolean isDone(){return (currentIndex == objs.length);}public Object currentItem(){return objs[currentIndex];}}}


5.迭代器模式的优缺点

(1)优点
  1. 将迭代过程封装到迭代器中,简化了聚集代码,并且简化了客户端的遍历代码。
  2. 每个聚集可以有几个不同的迭代器,互不影响。
  3. 封装性良好,客户端不必知道聚集的遍历算法,只要得到迭代器就可以使用
(2)缺点
  1. 迭代器容易让人产生聚集都是线性结构的错觉,有可能会得到意料之外的结果
  2. 对于简单聚集,例如ArrayList,迭代器比较繁琐。






原创粉丝点击