网页访问计数器

设计模式笔记(18)---迭代器模式(行为型)

Gof定义

提供一种方法顺序访问一个聚合对象中的各个元素, 而又不暴露该对象的内部表示。

动机

在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种优雅的方式。

迭代器模式结构图:

2010-01-24_190906

Aggregate:集合结构接口

Iterator:迭代器接口

Concreteaggregate:集合结构的具体类,继承Aggregate接口

ConcreteIteator:具体的迭代器类

代码实现:

/// <summary>
/// 集合结构接口
/// </summary>
public interface Aggregate
{
    Iterator CreateIterator();
}
/// <summary>
/// 迭代器接口
/// </summary>
public interface Iterator
{
    object First();
    object Next();
    bool IsDone();
    object CurrentItem();
}
/// <summary>
/// 集合结构的具体类
/// </summary>
class ConcreteAggregate : Aggregate
{
    private List<object> items = new List<object>();
    public Iterator CreateIterator()
    {
        return new ConcreteIterator(this);
    }
    public int Count
    {
        get { return items.Count; }
    }
    public object this[int index]
    {
        get { return items[index]; }
        set { items.Insert(index, value); }
    }
}
/// <summary>
/// 具体的迭代器类
/// </summary>
class ConcreteIterator : Iterator
{
    private ConcreteAggregate _aggregate;
    private int _current = 0;
    public ConcreteIterator(ConcreteAggregate aggregate)
    {
        this._aggregate = aggregate;
    }
    public object First()
    {
        return _aggregate[0];
    }
    public object Next()
    {
        object r = null;
        _current++;
        if (_current < _aggregate.Count)
        {
            r = _aggregate[_current];
        }
        return r;
    }
    public bool IsDone()
    {
        return _current >= _aggregate.Count ? true : false;
    }
    public object CurrentItem()
    {
        return _aggregate[_current];
    }
}
/// <summary>
/// 客户端调用
/// </summary>
class Program
{
    static void Main(string[] args)
    {
        ConcreteAggregate ca = new ConcreteAggregate();
        ca[0] = "AspNet3.5 揭秘";
        ca[0] = "重构:改善既有代码的设计";
        ca[2] = "设计模式";
        ca[3] = "人月神话";
        ca[4] = "代码大全2";
        Iterator i = new ConcreteIterator(ca);
        while (!i.IsDone())
        {
            Console.WriteLine("要读的书:" + i.CurrentItem());
            i.Next();
        }
    }
}

上面的代码是根据结构图实现的基础代码,在设计的运用中可以使用Net框架给我们提供的相关接口IEnumerableIEnumerator,这两个接口在Net中的实现代码如下:

public interface IEnumerable
{
    IEmumerator GetEnumerator();
}
public interface IEmumerator
{
    Object Current { get; }
    bool MoveNext();
    void Reset();
}

在Net中List实现了IEnumerable接口,下面的代码将List作为数据的容器来实现遍历:

class Program
{
    static void Main(string[] args)
    {
        List<string> list = new List<string> 
        { 
            "AspNet3.5 揭秘","重构:改善既有代码的设计","设计模式",
            "人月神话","代码大全2"
        };

        IEnumerator i = list.GetEnumerator();
        while (i.MoveNext())
        {
            Console.WriteLine("要读的书:" + i.Current);
        }
    }
}

上面的代码中试调用List的GetEnumerator方法返回IEmumerator类型的集合,然后取遍历,这样仍然显得比较麻烦,其实在Net中foreach已经实现了这样的功能,代码如下:

class Program
{
    static void Main(string[] args)
    {
        List<string> list = new List<string> 
        { 
            "AspNet3.5 揭秘","重构:改善既有代码的设计","设计模式",
            "人月神话","代码大全2"
        };
        foreach (string s in list)
        {
            Console.WriteLine("要读的书:" + s);
        }
    }
}

可以看出foreach其实就是实现了下面这段代码

IEnumerator i = list.GetEnumerator();
while (i.MoveNext())
{
    Console.WriteLine("要读的书:" + i.Current);
}

Iterator模式的几个要点

  • 迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。
    迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
    迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。

返回开篇(索引)

posted @ 2010-01-24 20:56  oec2003  阅读(431)  评论(0编辑  收藏  举报