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

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,迭代器比较繁琐。






评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值