Unity实现设计模式——迭代器模式
Unity实现设计模式——迭代器模式
迭代器模式是一种行为型设计模式,它提供了一种统一的方式来访问集合对象中的元素,而不是暴露集合内部的表示方式。简单地说,就是将遍历集合的责任封装到一个单独的对象中,我们可以按照特定的方式访问集合中的元素。
抽象迭代器(Iterator):定义了遍历聚合对象所需的方法,包括hashNext()和next()方法等,用于遍历聚合对象中的元素。
具体迭代器(Concrete Iterator):它是实现迭代器接口的具体实现类,负责具体的遍历逻辑。它保存了当前遍历的位置信息,并可以根据需要向前或向后遍历集合元素。
抽象聚合器(Aggregate): 一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
具体聚合器(ConcreteAggregate):就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。
简单来说就是容器的种类我们不需要知道是什么(List,HasSet等)我们只要获取到迭代器就可以进行遍历。
下面使用两个例子来说明
1.抽象的例子
(一)Aggregate
抽象聚合器
abstract class Aggregate{public abstract Iterator CreateIterator();}
(二)ConcreteAggregate
具体聚合器
class ConcreteAggregate : Aggregate{private ArrayList _items = new ArrayList();public override Iterator CreateIterator(){return new ConcreteIterator(this);}// Gets item countpublic int Count{get { return _items.Count; }}// Indexerpublic object this[int index]{get { return _items[index]; }set { _items.Insert(index, value); }}}
(三)Iterator
抽象迭代器
abstract class Iterator{public abstract object First();public abstract object Next();public abstract bool IsDone();public abstract object CurrentItem();}
(四)ConcreteIterator
具体迭代器
class ConcreteIterator : Iterator{private ConcreteAggregate _aggregate;private int _current = 0;// Constructorpublic ConcreteIterator(ConcreteAggregate aggregate){this._aggregate = aggregate;}// Gets first iteration itempublic override object First(){return _aggregate[0];}// Gets next iteration itempublic override object Next(){object ret = null;if (_current < _aggregate.Count - 1){ret = _aggregate[++_current];}return ret;}// Gets current iteration itempublic override object CurrentItem(){return _aggregate[_current];}// Gets whether iterations are completepublic override bool IsDone(){return _current >= _aggregate.Count;}}
(五)测试
public class IteratorStructure : MonoBehaviour
{void Start ( ){ConcreteAggregate a = new ConcreteAggregate();a[0] = "Item A";a[1] = "Item B";a[2] = "Item C";a[3] = "Item D";// Create Iterator and provide aggregateIterator i = a.CreateIterator();Debug.Log("Iterating over collection:");object item = i.First();while (item != null){Debug.Log(item);item = i.Next();}}
}
2.现实例子
这里使用一个不同年代的歌曲集来进行演示
(一)SongInfo
歌曲信息
public class SongInfo{public string songName { get; protected set; }public string bandName { get; protected set; }public int yearReleased { get; protected set; }public SongInfo(string songName, string bandName, int yearReleased){this.songName = songName;this.bandName = bandName;this.yearReleased = yearReleased;}public string ToStringEx(){return this.songName + " - " + this.bandName + " : " + this.yearReleased.ToString();}}
(二)SongIterator
抽象迭代器
public interface SongIterator{IEnumerator GetIterator();}
(三)SongsOfThe70s
70年代歌曲,既是迭代器又是聚合器
public class SongsOfThe70s : SongIterator{// here it is a listprotected List<SongInfo> bestSongs;public SongsOfThe70s(){bestSongs = new List<SongInfo>();}public void AddSong(string name, string artist, int year){SongInfo song = new SongInfo(name, artist, year);bestSongs.Add(song);}//about yeild return :http://www.jb51.net/article/54810.htm// heartpublic IEnumerator GetIterator(){foreach (SongInfo song in bestSongs)yield return song;yield break;}}
(四)SongsOfThe80s
80年代歌曲,既是迭代器又是聚合器
public class SongsOfThe80s : SongIterator{// here we have an arrayprotected SongInfo[] bestSongs;public SongsOfThe80s(){bestSongs = new SongInfo[0];}public void AddSong(string name, string artist, int year){SongInfo song = new SongInfo(name, artist, year);// just for the sake of easyness of appending something we will convert the array to a listList<SongInfo> newSongs = new List<SongInfo>(bestSongs);// add a new elementnewSongs.Add(song);// and convert it back to an arraybestSongs = newSongs.ToArray();}// heartpublic IEnumerator GetIterator(){foreach (SongInfo song in bestSongs)yield return song;yield break;}}
(五)测试
void Start(){// creating the collections and adding some songs:SongsOfThe70s song70s = new SongsOfThe70s();song70s.AddSong("song title", "song artist", 1974);song70s.AddSong("song title2", "song artist2", 1978);SongsOfThe80s song80s = new SongsOfThe80s();song80s.AddSong("song title 80s", "song artist 80s", 1985);song80s.AddSong("song title2 80s", "song artist2 80s", 1989);// because of the iterator pattern we can loop through both types// of collections the same simple way and don't have to bother// with what type of collection the object stores:IEnumerator songsOfThe70sIterator = song70s.GetIterator();while (songsOfThe70sIterator.MoveNext()){SongInfo info = (SongInfo)songsOfThe70sIterator.Current;Debug.Log("Song 70s: " + info.ToStringEx());}IEnumerator songsOfThe80sIterator = song80s.GetIterator();while (songsOfThe80sIterator.MoveNext()){SongInfo info = (SongInfo)songsOfThe80sIterator.Current;Debug.Log("Song 80s: " + info.ToStringEx());}}