亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

(第Ⅳ部分 行為型模式篇) 第17章 迭代器模式(I

系統 2114 0
概述
在面向對象的軟件設計中,我們經常會遇到一類集合對象,這類集合對象的內部結構可能有著各種各樣的實現,但是歸結起來,無非有兩點是需要我們去關心的:一是集合內部的數據存儲結構,二是遍歷集合內部的數據。面向對象設計原則中有一條是類的單一職責原則,所以我們要盡可能的去分解這些職責,用不同的類去承擔不同的職責。Iterator模式就是分離了集合對象的遍歷行為,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明的訪問集合內部的數據。
意圖
提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。[GOF 《設計模式》]
結構圖
Iterator 模式結構圖如下:
圖1 Iterator模式結構圖
生活中的例子
迭代器提供一種方法順序訪問一個集合對象中各個元素,而又不需要暴露該對象的內部表示。在早期的電視機中,一個撥盤用來改變頻道。當改變頻道時,需要手工轉動撥盤移過每一個頻道,而不論這個頻道是否有信號。現在的電視機,使用[后一個]和[前一個]按鈕。當按下[后一個]按鈕時,將切換到下一個預置的頻道。想象一下在陌生的城市中的旅店中看電視。當改變頻道時,重要的不是幾頻道,而是節目內容。如果對一個頻道的節目不感興趣,那么可以換下一個頻道,而不需要知道它是幾頻道。
圖2 使用選頻器做例子的Iterator模式對象圖
Iterator 模式解說
在面向對象的軟件設計中,我們經常會遇到一類集合對象,這類集合對象的內部結構可能有著各種各樣的實現,但是歸結起來,無非有兩點是需要我們去關心的:一是集合內部的數據存儲結構,二是遍歷集合內部的數據。面向對象設計原則中有一條是類的單一職責原則,所以我們要盡可能的去分解這些職責,用不同的類去承擔不同的職責。Iterator模式就是分離了集合對象的遍歷行為,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明的訪問集合內部的數據。下面看一個簡單的示意性例子,類結構圖如下:
圖3 示例代碼結構圖
首先有一個抽象的聚集,所謂的聚集就是就是數據的集合,可以循環去訪問它。它只有一個方法GetIterator()讓子類去實現,用來獲得一個迭代器對象。
/**/ /// <summary>

/// 抽象聚集

/// </summary>


public interface IList

{
IIteratorGetIterator();
}
抽象的迭代器,它是用來訪問聚集的類,封裝了一些方法,用來把聚集中的數據按順序讀取出來。通常會有MoveNext()、CurrentItem()、Fisrt()、Next()等幾個方法讓子類去實現。
/**/ /// <summary>

/// 抽象迭代器

/// </summary>


public interface IIterator
{
bool MoveNext();

ObjectCurrentItem();

void First();

void Next();
}
具體的聚集,它實現了抽象聚集中的唯一的方法,同時在里面保存了一組數據,這里我們加上Length屬性和GetElement()方法是為了便于訪問聚集中的數據。
/**/ /// <summary>

/// 具體聚集

/// </summary>


public class ConcreteList:IList
{
int []list;

public ConcreteList()

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


public IIteratorGetIterator()

{
return new ConcreteIterator( this );
}


public int Length

{
get { return list.Length;}
}


public int GetElement( int index)

{
return list[index];
}

}
具體迭代器,實現了抽象迭代器中的四個方法,在它的構造函數中需要接受一個具體聚集類型的參數,在這里面我們可以根據實際的情況去編寫不同的迭代方式。
/**/ /// <summary>

/// 具體迭代器

/// </summary>


public class ConcreteIterator:IIterator

{
private ConcreteListlist;

private int index;

public ConcreteIterator(ConcreteListlist)

{
this .list = list;

index
= 0 ;
}


public bool MoveNext()

{
if (index < list.Length)

return true ;

else

return false ;
}


public ObjectCurrentItem()

{
return list.GetElement(index);
}


public void First()

{
index
= 0 ;
}


public void Next()

{
if (index < list.Length)

{
index
++ ;
}

}

}
簡單的客戶端程序調用:
/**/ /// <summary>

/// 客戶端程序

/// </summary>


class Program

{
static void Main( string []args)

{
IIteratoriterator;

IListlist
= new ConcreteList();

iterator
= list.GetIterator();

while (iterator.MoveNext())

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

iterator.Next();
}


Console.Read();

}


}
一個簡單的迭代器示例就結束了,這里我們并沒有利用任何的.NET特性,在C#中,實現Iterator模式已經不需要這么麻煩了,已經C#語言本身就有一些特定的實現,下面會說到。
.NET 中的Iterator模式
在.NET下實現Iterator模式,對于聚集接口和迭代器接口已經存在了,其中IEnumerator扮演的就是迭代器的角色,它的實現如下:
public interface IEumerator

{
object Current
{
get ;
}


bool MoveNext();

void Reset();

}
屬性Current返回當前集合中的元素,Reset()方法恢復初始化指向的位置,MoveNext()方法返回值true表示迭代器成功前進到集合中的下一個元素,返回值false表示已經位于集合的末尾。能夠提供元素遍歷的集合對象,在.Net中都實現了IEnumerator接口。
IEnumerable 則扮演的就是抽象聚集的角色,只有一個GetEnumerator()方法,如果集合對象需要具備跌代遍歷的功能,就必須實現該接口。
public interface IEnumerable

{
IEumeratorGetEnumerator();
}
下面看一個在 .NET1.1 下的迭代器例子,Person類是一個可枚舉的類。PersonsEnumerator類是一個枚舉器類。這個例子來自于 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 IEnumeratorGetEnumerator()
{
return new PersonsEnumerator( this );
}

}



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

private PersonsP;

public PersonsEnumerator(PersonsP)
{
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];
}

}

}
來看客戶端代碼的調用:
class Program
{
static void Main( string []args)
{
PersonsarrPersons
= new Persons( " Michel " , " Christine " , " Mathieu " , " Julien " );

foreach ( string s in arrPersons)

{
Console.WriteLine(s);
}


Console.ReadLine();
}

}
程序將輸出:
Michel

Christine

Mathieu

Julien
現在我們分析編譯器在執行foreach語句時到底做了什么,它執行的代碼大致如下:
class Program

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

IEnumeratore
= arrPersons.GetEnumerator();

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

}


Console.ReadLine();
}

}
可以看到這段代碼跟我們最前面提到的示例代碼非常的相似。同時在這個例子中,我們把大部分的精力都花在了實現迭代器和可迭代的類上面,在.NET2.0下面,由于有了yield return關鍵字,實現起來將更加的簡單優雅。下面我們把剛才的例子在2.0下重新實現一遍:
public class Persons:IEnumerable
{
string []m_Names;

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

Names.CopyTo(m_Names,
0 );
}


public IEnumeratorGetEnumerator()
{
foreach ( string s in m_Names)
{
yield
return s;
}

}

}


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

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


Console.ReadLine();
}

}
程序將輸出:
Michel

Christine

Mathieu

Julien
實現相同的功能,由于有了yield return關鍵字,變得非常的簡單。好了,關于.NET中的Iterator模式就說這么多了,更詳細的內容大家可以參考相關的資料。
效果及實現要點
1 .迭代抽象:訪問一個聚合對象的內容而無需暴露它的內部表示。
2 .迭代多態:為遍歷不同的集合結構提供一個統一的接口,從而支持同樣的算法在不同的集合結構上進行操作。
3 .迭代器的健壯性考慮:遍歷的同時更改迭代器所在的集合結構,會導致問題。
適用性
1 .訪問一個聚合對象的內容而無需暴露它的內部表示。
2 .支持對聚合對象的多種遍歷。
3 .為遍歷不同的聚合結構提供一個統一的接口(即, 支持多態迭代)。
總結
Iterator 模式就是分離了集合對象的遍歷行為,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明的訪問集合內部的數據。
參考資料
Erich Gamma 等,《設計模式:可復用面向對象軟件的基礎》,機械工業出版社
Robert C.Martin ,《敏捷軟件開發:原則、模式與實踐》,清華大學出版社
閻宏,《Java與模式》,電子工業出版社
Alan Shalloway James R. Trott ,《Design Patterns Explained》,中國電力出版社
MSDN WebCast 《C#面向對象設計模式縱橫談(18):Iterator 迭代器模式(行為型模式)》

(第Ⅳ部分 行為型模式篇) 第17章 迭代器模式(Iterator Pattern)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 天天操夜夜噜 | 神马影院我不卡影院 | 国产性较精品视频免费 | 极品粉嫩粉嫩福利视频在线 | 日本毛片大全 | 国产精品96久久久久久久 | 国产人成激情视频在线观看 | 国产成人在线看 | 久久精品欧美一区二区 | 不卡免费播放 | 国产女主播喷出白浆视频 | 偷拍肉窝窝视频在线播放 | 国产原创巨作精品 | 精品久久久一二三区 | 成人免费www在线高清观看 | 视频三区精品中文字幕 | 6一10周岁毛片在线 717影院理论午夜伦八戒 | 国产欧美亚洲精品第一区 | 草草影院国产第一页 | 婷婷 综合 | 欧美日本一道免费一区三区 | 欧美一级中文字幕 | 国产成人香蕉 | 女人l8毛片a一级毛片免费 | 欧美一级视频在线观看欧美 | 日韩欧美一区二区三区在线 | 久久精品免视看国产成人2021 | 性新婚a大黄毛片 | 亚洲精品国产美女在线观看 | 欧美日韩综合高清一区二区 | 久久婷婷五色综合夜啪 | 米奇影视7777 | 性夜影院爽黄a爽免费看网站 | 欧美线人一区二区三区 | 悠悠久久| 国内精品久久久久久西瓜色吧 | 999国产视频 | 欧美国产亚洲精品高清不卡 | 四虎成人永久影院 | 国产亚洲一区在线 | 人禽毛片|