设计模式之迭代器
迭代器模式介紹
集合的結構迭代器模式是一種行為設計模式,讓你能在不暴露集合底層表現形式(列表、棧、樹等)的情況下遍歷集合中所有的元素。
迭代器模式滿足了單一職責和開閉原則,外界的調用方也不需要知道任何一個不同的數據結構在使用上的遍歷差異。
迭代器模式的主要思想是將集合的遍歷行為抽取為單獨的迭代器對象。
除實現自身算法外,迭代器還封裝了遍歷操作的所有細節,比如當前位置和末尾剩余元素的數量、同時還有提供一個獲取集合元素的基本方法。客戶端可不斷調用該方法直到它不返回任何內容(已遍歷所有元素)、所有迭代器必須實現相同的接口(只要有合適的迭代器,客戶端代碼就能兼容任何類型的集合或遍歷算法)。
迭代器的結構
迭代器接口:聲明了遍歷集合所需的操作。(獲取下一個元素,獲取當前位置和重新開始迭代等)
具體迭代者:實現遍歷集合的一種特定算法。(迭代器必須跟蹤自身遍歷的進度)
集合接口:聲明一個或多個方法來獲取與集合兼容的迭代器。(返回方法的類型必須被聲明為迭代器接口,因此具體集合可以返回各種不同種類的迭代器)
具體集合:會在客戶端請求迭代器時返回一個特定的具體迭代器類。
客戶端:通過集合和迭代器的接口與兩者進行交互。這樣一來客戶端無需與具體類進行耦合,允許同一客戶端代碼使用各種不同的集合和迭代器。
應用場景
當集合背后為復雜的數據結構,且你希望對客戶端隱藏其復雜性時。
想避免程序中重復的遍歷代碼
程序代碼能夠遍歷不同的甚至是無法預知的數據結構時。
實現方式
1、聲明迭代器接口
2、聲明集合接口并描述一個獲取迭代器的方法,其返回值必須是迭代器接口。
3、為希望使用迭代器遍歷的集合實現具體的迭代器類。
4、在你的集合類中實現集合接口。
5、在客戶端使用迭代器替代所有集合遍歷代碼。
Demo
在迭代器的幫助下,客戶端可以用一個迭代器接口以相似的方式遍歷不同集合中的元素。
迭代器模式的辨別
迭代器可以通過導航方法(next和previous)來輕松識別。
使用迭代器的客戶端代碼可能沒有其所遍歷的集合的直接訪問權限(二者是完全分離的)。
下面羅列了一個對人員集合進行排序的迭代器模式。
人員迭代器
????///?<summary>///?人員迭代器///?繼承接口IEnumerator,顯示實現了Current、MoveNext、Reset方法。///?</summary>abstract?class?PeopleIterator:IEnumerator??{????????public?abstract?int?Key();public?abstract?object?Current();public?abstract?bool?MoveNext();??public?abstract?void?Reset();object?IEnumerator.Current{get?{?return?Current();?}}}抽象集合迭代器和其實現
????///?<summary>///?抽象的集合迭代器///?</summary>public?abstract?class?AggregateIterator?:IEnumerable{///?<summary>///?得到內部的集合///?</summary>///?<returns></returns>public?abstract?IEnumerator?GetEnumerator();}///?<summary>///?集合的迭代器類///?具體排序的邏輯在這里寫著///?</summary>class?AlphabeticalOrderIterator?:?PeopleIterator{private?PeopleCollection?_collection;private?int?_position?=?-1;private?bool?_reverse?=?false;public?AlphabeticalOrderIterator(PeopleCollection?collection,bool?reverse=false){this._collection?=?collection;_reverse?=?reverse;if?(reverse){_position?=?collection.getItems().Count;}????????????}///?<summary>///?當前的值///?</summary>///?<returns></returns>public?override?object?Current(){return?this._collection.getItems()[_position];???????????}///?<summary>///?此時的索引///?</summary>///?<returns></returns>public?override?int?Key(){return?this._position;}///?<summary>///?下一個??位置position進行調整///?</summary>///?<returns></returns>public?override?bool?MoveNext(){int?updatedPosition?=?this._position?+?(this._reverse???-1?:?1);if?(updatedPosition?>=?0?&&?updatedPosition?<?this._collection.getItems().Count){this._position?=?updatedPosition;return?true;}else{return?false;}}///?<summary>///?重置///?</summary>public?override?void?Reset(){this._position?=?this._reverse???this._collection.getItems().Count?-?1?:?0;}}具體的人員集合和其Main()方法驗證
????///?<summary>///?具體的人員集合///?</summary>public?class?PeopleCollection?:AggregateIterator{List<string>?_collection?=?new?List<string>();bool?_direction?=?false;public?void?ReverseDirection()?{_direction?=?!_direction;}public?List<string>?getItems()?{return?_collection;}public?void?AddItem(string?item)?{_collection.Add(item);}public?override?IEnumerator?GetEnumerator(){return?new?AlphabeticalOrderIterator(this,_direction);}}class?Program{static?void?Main(string[]?args){var?collection?=?new?PeopleCollection();collection.AddItem("阿五");collection.AddItem("阿六");collection.AddItem("阿七");Console.WriteLine("遍歷下");foreach?(var?item?in?collection){Console.WriteLine(item);}Console.WriteLine("倒序");collection.ReverseDirection();foreach?(var?item?in?collection){Console.WriteLine(item);}Console.ReadKey();}} 輸出結果迭代器模式在理解上還是有一點難度的,因為平時在使用集合時各個語言都已經將集合的各種操作方法都已經羅列出來了,調用人員直觀調用即可。所以我們在了解其設計模式思想時,還是要多進行實踐和思考。
有些東西看的多了,做的多了,自然而然就明白了。
小寄語
人生短暫,我不想去追求自己看不見的,我只想抓住我能看的見的。
原創不易,給個關注。
我是阿輝,感謝您的閱讀,如果對你有幫助,麻煩關注、點贊、轉發 謝謝。
總結
- 上一篇: 如何摆脱「自我否定」状态
- 下一篇: 如何禁用 ASP.NET 网站的所有的