日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

.NET设计模式(18):迭代器模式(Iterator Pattern)(转)

發(fā)布時(shí)間:2025/5/22 155 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET设计模式(18):迭代器模式(Iterator Pattern)(转) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

概述

在面向?qū)ο蟮能浖O(shè)計(jì)中,我們經(jīng)常會遇到一類集合對象,這類集合對象的內(nèi)部結(jié)構(gòu)可能有著各種各樣的實(shí)現(xiàn),但是歸結(jié)起來,無非有兩點(diǎn)是需要我們?nèi)リP(guān)心的:一是集合內(nèi)部的數(shù)據(jù)存儲結(jié)構(gòu),二是遍歷集合內(nèi)部的數(shù)據(jù)。面向?qū)ο笤O(shè)計(jì)原則中有一條是類的單一職責(zé)原則,所以我們要盡可能的去分解這些職責(zé),用不同的類去承擔(dān)不同的職責(zé)。Iterator模式就是分離了集合對象的遍歷行為,抽象出一個(gè)迭代器類來負(fù)責(zé),這樣既可以做到不暴露集合的內(nèi)部結(jié)構(gòu),又可讓外部代碼透明的訪問集合內(nèi)部的數(shù)據(jù)。

意圖

提供一種方法順序訪問一個(gè)聚合對象中各個(gè)元素, 而又不需暴露該對象的內(nèi)部表示。[GOF 《設(shè)計(jì)模式》]

結(jié)構(gòu)圖

Iterator模式結(jié)構(gòu)圖如下:

1 ?Iterator模式結(jié)構(gòu)圖

生活中的例子

迭代器提供一種方法順序訪問一個(gè)集合對象中各個(gè)元素,而又不需要暴露該對象的內(nèi)部表示。在早期的電視機(jī)中,一個(gè)撥盤用來改變頻道。當(dāng)改變頻道時(shí),需要手工轉(zhuǎn)動(dòng)撥盤移過每一個(gè)頻道,而不論這個(gè)頻道是否有信號。現(xiàn)在的電視機(jī),使用[后一個(gè)][前一個(gè)]按鈕。當(dāng)按下[后一個(gè)]按鈕時(shí),將切換到下一個(gè)預(yù)置的頻道。想象一下在陌生的城市中的旅店中看電視。當(dāng)改變頻道時(shí),重要的不是幾頻道,而是節(jié)目內(nèi)容。如果對一個(gè)頻道的節(jié)目不感興趣,那么可以換下一個(gè)頻道,而不需要知道它是幾頻道。

2 ?使用選頻器做例子的Iterator模式對象圖

Iterator模式解說

在面向?qū)ο蟮能浖O(shè)計(jì)中,我們經(jīng)常會遇到一類集合對象,這類集合對象的內(nèi)部結(jié)構(gòu)可能有著各種各樣的實(shí)現(xiàn),但是歸結(jié)起來,無非有兩點(diǎn)是需要我們?nèi)リP(guān)心的:一是集合內(nèi)部的數(shù)據(jù)存儲結(jié)構(gòu),二是遍歷集合內(nèi)部的數(shù)據(jù)。面向?qū)ο笤O(shè)計(jì)原則中有一條是類的單一職責(zé)原則,所以我們要盡可能的去分解這些職責(zé),用不同的類去承擔(dān)不同的職責(zé)。Iterator模式就是分離了集合對象的遍歷行為,抽象出一個(gè)迭代器類來負(fù)責(zé),這樣既可以做到不暴露集合的內(nèi)部結(jié)構(gòu),又可讓外部代碼透明的訪問集合內(nèi)部的數(shù)據(jù)。下面看一個(gè)簡單的示意性例子,類結(jié)構(gòu)圖如下:

3 示例代碼結(jié)構(gòu)圖

首先有一個(gè)抽象的聚集,所謂的聚集就是就是數(shù)據(jù)的集合,可以循環(huán)去訪問它。它只有一個(gè)方法GetIterator()讓子類去實(shí)現(xiàn),用來獲得一個(gè)迭代器對象。

/**////?<summary>

///?抽象聚集

///?</summary>


public?interface?IList

{
????IIterator?GetIterator();
}

抽象的迭代器,它是用來訪問聚集的類,封裝了一些方法,用來把聚集中的數(shù)據(jù)按順序讀取出來。通常會有MoveNext()CurrentItem()Fisrt()Next()等幾個(gè)方法讓子類去實(shí)現(xiàn)。

/**////?<summary>

///?抽象迭代器

///?</summary>


public?interface?IIterator
{
????
bool?MoveNext();

????Object?CurrentItem();

????
void?First();

????
void?Next();
}

具體的聚集,它實(shí)現(xiàn)了抽象聚集中的唯一的方法,同時(shí)在里面保存了一組數(shù)據(jù),這里我們加上Length屬性和GetElement()方法是為了便于訪問聚集中的數(shù)據(jù)。

/**////?<summary>

///?具體聚集

///?</summary>

public?class?ConcreteList?:?IList
{
????
int[]?list;

????
public?ConcreteList()

????
{
????????list?
=?new?int[]?{?1,2,3,4,5};
????}


????
public?IIterator?GetIterator()

????
{
????????
return?new?ConcreteIterator(this);
????}


????
public?int?Length

????
{
????????
get?{?return?list.Length;?}
????}


????
public?int?GetElement(int?index)

????
{
????????
return?list[index];
????}

}

具體迭代器,實(shí)現(xiàn)了抽象迭代器中的四個(gè)方法,在它的構(gòu)造函數(shù)中需要接受一個(gè)具體聚集類型的參數(shù),在這里面我們可以根據(jù)實(shí)際的情況去編寫不同的迭代方式。

/**////?<summary>

///?具體迭代器

///?</summary>

public?class?ConcreteIterator?:?IIterator

{
????
private?ConcreteList?list;

????
private?int?index;

????
public?ConcreteIterator(ConcreteList?list)

????
{
????????
this.list?=?list;

????????index?
=?0;
????}


????
public?bool?MoveNext()

????
{
????????
if?(index?<?list.Length)

????????????
return?true;

????????
else

????????????
return?false;
????}


????
public?Object?CurrentItem()

????
{
????????
return?list.GetElement(index)?;
????}


????
public?void?First()

????
{
????????index?
=?0;
????}


????
public?void?Next()

????
{
????????
if?(index?<?list.Length)

????????
{
????????????index
++;
????????}

????}

}

簡單的客戶端程序調(diào)用:

/**////?<summary>

///?客戶端程序

///?</summary>

class?Program

{
????
static?void?Main(string[]?args)

????
{
????????IIterator?iterator;

????????IList?list?
=?new?ConcreteList();

????????iterator?
=?list.GetIterator();

????????
while?(iterator.MoveNext())

????????
{
????????????
int?i?=?(int)iterator.CurrentItem();
????????????Console.WriteLine(i.ToString());

????????????iterator.Next();
????????}


????????Console.Read();

????}


}

一個(gè)簡單的迭代器示例就結(jié)束了,這里我們并沒有利用任何的.NET特性,在C#中,實(shí)現(xiàn)Iterator模式已經(jīng)不需要這么麻煩了,已經(jīng)C#語言本身就有一些特定的實(shí)現(xiàn),下面會說到。

.NET中的Iterator模式

.NET下實(shí)現(xiàn)Iterator模式,對于聚集接口和迭代器接口已經(jīng)存在了,其中IEnumerator扮演的就是迭代器的角色,它的實(shí)現(xiàn)如下:

public?interface?IEumerator

{
????
object?Current
????
{
????????
get;
????}


????
bool?MoveNext();

????
void?Reset();

}

屬性Current返回當(dāng)前集合中的元素,Reset()方法恢復(fù)初始化指向的位置,MoveNext()方法返回值true表示迭代器成功前進(jìn)到集合中的下一個(gè)元素,返回值false表示已經(jīng)位于集合的末尾。能夠提供元素遍歷的集合對象,在.Net中都實(shí)現(xiàn)了IEnumerator接口。

IEnumerable則扮演的就是抽象聚集的角色,只有一個(gè)GetEnumerator()方法,如果集合對象需要具備跌代遍歷的功能,就必須實(shí)現(xiàn)該接口。

public?interface?IEnumerable

{
????IEumerator?GetEnumerator();
}

下面看一個(gè)在.NET1.1下的迭代器例子,Person類是一個(gè)可枚舉的類。PersonsEnumerator類是一個(gè)枚舉器類。這個(gè)例子來自于http://www.theserverside.net/,被我簡單的改造了一下。

public?class?Persons?:?IEnumerable?

{?
????
public?string[]?m_Names;?

????
public?Persons(params?string[]?Names)?
????
{?
????????m_Names?
=?new?string[Names.Length];?

????????Names.CopyTo(m_Names,
0);?
????}
?

????
private?string?this[int?index]?
????
{?
????????
get?
????????
{?
????????????
return?m_Names[index];?
????????}
?

????????
set?
????????
{?
????????????m_Names[index]?
=?value;?
????????}
?
????}


????
public?IEnumerator?GetEnumerator()
????
{
????????
return?new?PersonsEnumerator(this);
????}

}



public?class?PersonsEnumerator?:?IEnumerator
{
????
private?int?index?=?-1;

????
private?Persons?P;

????
public?PersonsEnumerator(Persons?P)
????
{
????????
this.P?=?P;
????}


????
public?bool?MoveNext()
????
{
????????index
++;

????????
return?index?<?P.m_Names.Length;
????}


????
public?void?Reset()
????
{
????????index?
=?-1;
????}


????
public?object?Current
????
{
????????
get

????????
{
????????????
return?P.m_Names[index];
????????}

????}

}
?

來看客戶端代碼的調(diào)用:

class?Program?
{?
????
static?void?Main(string[]?args)?
????
{?
????????Persons?arrPersons?
=?new?Persons("Michel","Christine","Mathieu","Julien");?

????????
foreach?(string?s?in?arrPersons)?

????????
{?
????????????Console.WriteLine(s);?
????????}


????????Console.ReadLine();?
????}
?
}

程序?qū)⑤敵?#xff1a;

Michel?

Christine?

Mathieu?

Julien

現(xiàn)在我們分析編譯器在執(zhí)行foreach語句時(shí)到底做了什么,它執(zhí)行的代碼大致如下:

class?Program?

{?
????
static?void?Main(string[]?args)?
????
{?
??????????Persons?arrPersons?
=?new?Persons("Michel","Christine","Mathieu","Julien");?

??????????IEnumerator?e?
=?arrPersons.GetEnumerator();?

??????????
while?(e.MoveNext())?
??????????
{?
????????????Console.WriteLine((
string)e.Current);?

??????????}


??????????Console.ReadLine();
????}
?
}

可以看到這段代碼跟我們最前面提到的示例代碼非常的相似。同時(shí)在這個(gè)例子中,我們把大部分的精力都花在了實(shí)現(xiàn)迭代器和可迭代的類上面,在.NET2.0下面,由于有了yield return關(guān)鍵字,實(shí)現(xiàn)起來將更加的簡單優(yōu)雅。下面我們把剛才的例子在2.0下重新實(shí)現(xiàn)一遍:

public?class?Persons?:?IEnumerable?
{?
????
string[]?m_Names;?

????
public?Persons(params?string[]?Names)?
????
{?
????????m_Names?
=?new?string[Names.Length];?

????????Names.CopyTo(m_Names,
0);?
????}
?

????
public?IEnumerator?GetEnumerator()?
????
{?
????????
foreach?(string?s?in?m_Names)?
????????
{?
????????????yield?
return?s;?
????????}
?
????}
?
}
?

class?Program?
{?
????
static?void?Main(string[]?args)?
????
{?
????????Persons?arrPersons?
=?new?Persons("Michel","Christine","Mathieu","Julien");?

????????
foreach?(string?s?in?arrPersons)?
????????
{?
????????????Console.WriteLine(s);?
????????}


????????Console.ReadLine();?
????}
?
}

程序?qū)⑤敵?#xff1a;

Michel?

Christine?

Mathieu?

Julien

實(shí)現(xiàn)相同的功能,由于有了yield return關(guān)鍵字,變得非常的簡單。好了,關(guān)于.NET中的Iterator模式就說這么多了,更詳細(xì)的內(nèi)容大家可以參考相關(guān)的資料。

效果及實(shí)現(xiàn)要點(diǎn)

1.迭代抽象:訪問一個(gè)聚合對象的內(nèi)容而無需暴露它的內(nèi)部表示。

2.迭代多態(tài):為遍歷不同的集合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口,從而支持同樣的算法在不同的集合結(jié)構(gòu)上進(jìn)行操作。

3.迭代器的健壯性考慮:遍歷的同時(shí)更改迭代器所在的集合結(jié)構(gòu),會導(dǎo)致問題。

適用性

1.訪問一個(gè)聚合對象的內(nèi)容而無需暴露它的內(nèi)部表示。

2.支持對聚合對象的多種遍歷。

3.為遍歷不同的聚合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口(, 支持多態(tài)迭代)

總結(jié)

Iterator模式就是分離了集合對象的遍歷行為,抽象出一個(gè)迭代器類來負(fù)責(zé),這樣既可以做到不暴露集合的內(nèi)部結(jié)構(gòu),又可讓外部代碼透明的訪問集合內(nèi)部的數(shù)據(jù)。

參考資料

Erich Gamma等,《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》,機(jī)械工業(yè)出版社

Robert C.Martin,《敏捷軟件開發(fā):原則、模式與實(shí)踐》,清華大學(xué)出版社

閻宏,《Java與模式》,電子工業(yè)出版社

Alan Shalloway James R. Trott,《Design Patterns Explained》,中國電力出版社

MSDN WebCast C#面向?qū)ο笤O(shè)計(jì)模式縱橫談(18)Iterator 迭代器模式(行為型模式)

總結(jié)

以上是生活随笔為你收集整理的.NET设计模式(18):迭代器模式(Iterator Pattern)(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。