3.4.1 模式意圖:
系統(tǒng)中會有對集合的元素進(jìn)行自增或者自減順序的訪問操作胀蛮,對于這種需求我們可以使用迭代器模式來建立對應(yīng)的迭代器,C#自帶的
IEnumerator
也是利用了這種模式的特點(diǎn)退腥。
3.4.2 模式概念:
它屬于行為型模式狡刘,提供一種方法困鸥,順序訪問聚合對象中的各個元素疾就,而又不暴露該對象的內(nèi)部表示。
3.4.3 模式元素:
- 迭代器抽象(IIterator)
- 迭代器細(xì)節(jié)(ConcreteIterator)
- 需要迭代的集合(Group)
3.4.4 代碼示例:
下面筆者逐步完成迭代器模式的構(gòu)建鸟废。
創(chuàng)建一個簡單的集合侮攀。
public class Group
{
private IList<object> items = new List<object>();
public int Count
{
get { return items.Count; }
}
public object this[int index]
{
get { return items[index]; }
set { items.Insert(index, value); }
}
}
為了讓多種集合都能使用同一種遍歷方式厢拭,我們再創(chuàng)建一個通用迭代器供鸠。
public class ConcreteIterator
{
private IList<object> items = new List<object>();
public Iterator(IList<object> tempItems)
{
items = tempItems;
}
private int index = -1;
public object Current
{
get { return items[index]; }
}
public bool MoveNext()
{
return items.Count > ++index;
}
public void Reset()
{
index = -1;
}
}
然后把迭代器鑲嵌到這個集合中。
public class Group
{
private IList<object> items = new List<object>();
public int Count
{
get { return items.Count; }
}
public object this[int index]
{
get { return items[index]; }
set { items.Insert(index, value); }
}
public ConcreteIterator GetIterator()
{
return new ConcreteIterator(items);
}
}
調(diào)用示例代碼薄坏。
void Start()
{
Group group = new Group();
group[0] = "愛";
group[1] = "生";
group[2] = "活";
group[3] = "愛";
group[4] = "海";
group[5] = "瀾";
Iterator iterator = group.GetIterator();
while (iterator.MoveNext())
{
this.Log($"現(xiàn)在的元素為:{iterator.Current}");
}
}
開始重構(gòu)
在
Iterator
中不能確定這個遍歷的集合是列表胶坠、字典還是數(shù)組沈善,但是可以確定他們都含有Current
、MoveNext
與Reset
三種元素闻牡,所以將這三種元素進(jìn)行抽象罩润,與原來的迭代器類進(jìn)行剝離。
public interface IIterator
{
object Current { get; }
bool MoveNext();
void Reset();
}
原迭代器類繼承接口
IIterator
金度。
public class ConcreteIterator: IIterator
{
private IList<object> items = new List<object>();
public Iterator(IList<object> tempItems)
{
items = tempItems;
}
private int index = -1;
public object Current
{
get { return items[index]; }
}
public bool MoveNext()
{
return items.Count > ++index;
}
public void Reset()
{
index = -1;
}
}
既然原迭代器類繼承接口
IIterator
猜极,那么可以根據(jù)這個接口所規(guī)定的結(jié)構(gòu)祝峻,讓細(xì)節(jié)的實現(xiàn)統(tǒng)統(tǒng)轉(zhuǎn)移到子類中實現(xiàn),也就是說酬姆,我們可以定義出多種滿足不同迭代需求的迭代類辞色,但是調(diào)用的函數(shù)都是一樣的浮定。根據(jù)里氏替換原則可知,對應(yīng)的Group中所返回的public Iterator GetIterator()
完全可以用接口IIterator
代替立美。
public class Group
{
private IList<object> items = new List<object>();
public int Count
{
get { return items.Count; }
}
public object this[int index]
{
get { return items[index]; }
set { items.Insert(index, value); }
}
public IIterator GetIterator()
{
return new ConcreteIterator(items);
}
}
最后建蹄,為了區(qū)分什么樣子的集合可以使用通用迭代模式裕偿,我們做一個獲得迭代器的接口,只要繼承這個接口的集合劲腿,就都可以使用通用迭代模式了鸟妙。
public interface IEnumerable
{
ConcreteIterator GetIterator();
}
public class Group: IEnumerable
{
private IList<object> items = new List<object>();
public int Count
{
get { return items.Count; }
}
public object this[int index]
{
get { return items[index]; }
set { items.Insert(index, value); }
}
public IIterator GetIterator()
{
return new ConcreteIterator(items);
}
}
3.4.5 寫法對比:
略
3.4.6 模式分析:
經(jīng)過剝離和抽象,我們的迭代器模式就完成了垃瞧。迭代器就是把原有需要遍歷的結(jié)構(gòu)進(jìn)行一次包裝坪郭,把包裝后的結(jié)構(gòu)再統(tǒng)一進(jìn)行遍歷。
其實在C# 中自帶的迭代器要比我們這個更強(qiáng)大嗦锐,它最大的特點(diǎn)就是按需逐步查詢 Unity 之?dāng)?shù)據(jù)集合解析中的最后IEnumerable補(bǔ)充部分有例子說明沪曙,這里就不在熬述。
3.4.7 應(yīng)用場景:
需要按指定順序迭代查詢集合中的元素碳默。
3.4.8 小結(jié):
如果系統(tǒng)自帶的迭代器更好缘眶,就用系統(tǒng)的,這種無用的輪子我們還是不要浪費(fèi)時間再造了该抒,了解下原理就好顶燕。