首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET 設計模式精解(十八):迭代器模式——封裝遍歷邏輯,實現集合與演算法解耦

     編輯:關於.NET

面向物件設計中,集合物件內部結構多樣 (陣列、鏈表、樹等),但外部僅關心兩點:資料儲存結構與遍歷方式。單一職責原則要求分離遍歷行為,迭代器模式應運而生:抽象出迭代器類別負責遍歷,不暴露集合內部表示,讓外部代碼透明存取集合元素。

一、模式意圖與結構

意圖:提供方法循序存取聚合物件元素,且不暴露內部表示。(GoF)

結構圖:

迭代器模式結構圖

二、生活實例:電視選頻

早期電視撥盤需手動掃描每個頻道;現代遙控器「上/下一台」按鈕即為迭代器:使用者只關心節目內容,不需知道頻道號碼:

選頻器迭代器模式示意

三、手工實作迭代器模式 (教學範例)

抽象層

public interface IList { IIterator GetIterator(); }
public interface IIterator {
    bool MoveNext();
    object CurrentItem();
    void First();
    void Next();
}

具體實作

public class ConcreteList : IList {
    private int[] _list = {1,2,3,4,5};
    public IIterator GetIterator() => new ConcreteIterator(this);
    public int Length => _list.Length;
    public int GetElement(int index) => _list[index];
}
public class ConcreteIterator : IIterator {
    private ConcreteList _list; private int _index;
    public ConcreteIterator(ConcreteList list) { _list = list; _index = 0; }
    public bool MoveNext() => _index < _list.Length;
    public object CurrentItem() => _list.GetElement(_index);
    public void First() => _index = 0;
    public void Next() { if (_index < _list.Length) _index++; }
}

用戶端調用

IList list = new ConcreteList();
IIterator it = list.GetIterator();
while (it.MoveNext()) {
    Console.WriteLine(it.CurrentItem());
    it.Next();
}

四、.NET 框架內建迭代器支援

.NET 1.x 介面

public interface IEnumerator {
    object Current { get; }
    bool MoveNext();
    void Reset();
}
public interface IEnumerable { IEnumerator GetEnumerator(); }

範例:可枚舉的 Persons 類別

public class Persons : IEnumerable {
    private string[] _names;
    public Persons(params string[] names) { _names = names; }
    public IEnumerator GetEnumerator() => new PersonsEnumerator(this);
}
public class PersonsEnumerator : IEnumerator {
    private Persons _p; private int _index = -1;
    public PersonsEnumerator(Persons p) { _p = p; }
    public bool MoveNext() => ++_index < _p._names.Length;
    public void Reset() => _index = -1;
    public object Current => _p._names[_index];
}

foreach 編譯器展開原理

IEnumerator e = arrPersons.GetEnumerator();
while (e.MoveNext()) Console.WriteLine((string)e.Current);

五、.NET 2.0+ yield return 簡化實作

public class Persons : IEnumerable {
    private string[] _names;
    public Persons(params string[] names) { _names = names; }
    public IEnumerator GetEnumerator() {
        foreach (var s in _names) yield return s;
    }
}

極大簡化迭代器實作,編譯器自動生成狀態機代碼。

六、效果、實現要點與適用性

  • 迭代抽象:存取聚合內容不暴露內部結構。
  • 迭代多型:統一介面支援不同集合結構遍歷,演算法可復用。
  • 健壯性:遍歷過程修改集合結構會導致問題 (需考慮快照或版本機制)。
  • 適用場景:隱藏內部表示、支援多種遍歷方式、多型迭代。

七、總結

迭代器模式分離集合遍歷行為,封裝於專責迭代器類別,實現集合與演算法解耦。.NET 透過 IEnumerable/IEnumerator 介面與 yield return 語法提供一級公民支援,開發者應善用框架機制而非重複造輪子。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved