設計模式筆記(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模式的幾個要點

  • 迭代抽象:訪問一個聚合對象的內容而無需暴露它的內部表示。
    迭代多態:爲遍歷不同的集合結構提供一個統一的接口,從而支持同樣的算法在不同的集合結構上進行操作。
    迭代器的健壯性考慮:遍歷的同時更改迭代器所在的集合結構,會導致問題。
發佈了115 篇原創文章 · 獲贊 1 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章