設計模式(17) 迭代器模式

  • 迭代器模式
  • 基於IEnumerable的實現
  • 使用場景
  • 迭代器模式的優缺點

迭代器模式

迭代器模式用於順序訪問集合對象的元素,而不須要知道集合對象的底層表示。Java和.Net等語言已經將迭代器做爲其內部語法元素,好比在C#中,集合對象只須要實現IEnumberable接口,而後就能夠用foreach來遍歷了。
迭代器模式提示咱們要從使用者的角度考慮如何設計接口,如何對外提供訪問內部對象的方式。即使咱們組織的對象系統內部結構很複雜,但對於客戶程序而言最簡單的方式莫過於經過for /foreach循環依次遍歷,至於遍歷過程當中的次序、分類篩選等則由目標類型本身封裝。設計模式

GOF對迭代器模式描述爲:
Provide a way to access the elements of an aggregate objectsequentially without exposing its underlying representation.
— Design Patterns : Elements of Reusable Object-Oriented Softwareide

UML類圖:
this

代碼實現設計

//迭代器接口
public interface IIterator<T>
{
    T Next();
    bool HasNext();
}
//具體迭代器
public class ConcreteIterator<T> : IIterator<T>
{
    private ConcreteAggretate<T> Aggretate; //成員變量,關聯關係
    private int cursor = 0;
    public ConcreteIterator(ConcreteAggretate<T> agg)
    {
        this.Aggretate = agg;
    }
    public bool HasNext()
    {
        return !(cursor >= Aggretate.Size);
    }

    public T Next()
    {
        if (HasNext())
        {
            return Aggretate.GetELement(cursor++);
        }
        else
        {
            return default(T);
        }

    }
}
//聚合接口
public interface IAggretate<T>
{
    public void Add(T obj);
    public void Remove(T obj);
    public int Size { get; }
    public T GetELement(int index);
    public IIterator<T> GetIterator();
}
//具體聚合
public class ConcreteAggretate<T> : IAggretate<T>
{
    private List<T> list = new List<T>();  //
    public void Add(T obj)
    {
        list.Add(obj);
    }

    public void Remove(T obj)
    {
        list.Remove(obj);
    }

    public IIterator<T> GetIterator()
    {
        return new ConcreteIterator<T>(this);  //在局部方法中new實例,屬依賴關係
    }

    public int Size
    {
        get
        {
            return list.Count;
        }
    }

    public T GetELement(int index)
    {
        return list[index];
    }
}

調用者代碼:code

IAggretate<int> aggretate = new ConcreteAggretate<int>();
aggretate.Add(9);
aggretate.Add(8);
aggretate.Add(7);
IIterator<int> iterator = aggretate.GetIterator();
while (iterator.HasNext())
{
    Console.WriteLine(iterator.Next());
}

基於IEnumerable的實現

以上即是經典的迭代器模式的實現,這種模式給聚合對象增長了一個建立其迭代器對象的方法,迭代器的抽象定義和具體迭代器類型都做爲一個額外的對象存在。
實際上C#已內置了對迭代器模式的支持,只須要實現IEnumerable接口便可,再也不須要從0開始,少了不少代碼量:對象

public class ConcreteAggretate<T> : IEnumerable<T>
{
    private List<T> list = new List<T>();
    public void Add(T obj)
    {
        list.Add(obj);
    }

    public void Remove(T obj)
    {
        list.Remove(obj);
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (var item in list)
        {
            yield return item;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

使用foreach遍歷IEnumerable接口blog

var aggretate = ConcreteAggretate<int>();
aggretate.Add(9);
aggretate.Add(8);
aggretate.Add(7);

foreach (var item in aggretate)
{
    Console.WriteLine(item);
}

使用場景

  • 對象內部結構比較複雜,爲了讓調用者能夠輕鬆地訪問,同時不須要暴露其內部結構;
  • 須要爲聚合對象提供多種遍歷方式;
  • 爲遍歷不一樣的聚合結構提供一個統一的接口;

迭代器模式的優缺點

優勢接口

  • 迭代器支持以不一樣的方式遍歷一個聚合對象,並且在同一個聚合上能夠添加多個具備不一樣遍歷方式的迭代器;
  • 迭代器簡化了聚合類的遍歷;
  • 迭代器模式能夠方便地增長新的聚合類和迭代器類,無須修改原有代碼。

缺點
迭代器模式經過將存儲數據和遍歷數據的職責分離,爲封裝集合地複雜性、隔離變化提供了極大的遍歷,但這種方式也有其固有的缺點:每次
增長新的聚合類都須要對應增長新的迭代器類,類的個數成對增長,這在必定程度上增長了系統的複雜性。element

參考書籍:
王翔著 《設計模式——基於C#的工程化實現及擴展》get

相關文章
相關標籤/搜索