前进中的蜗牛

番茄大叔

水滴穿石,非一日之功;没有量变,何来质变。

迭代器模式(Iterator Pattern)

模式定义

提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。

UML类图

  • 抽象迭代角色(Iterator) 负责定义访问和遍历元素的接口(如Next()下一个元素,IsDone()集合是否变量完,CurrentItem()当前元素等)
  • 具体迭代角色(Concrete Iterator) 关联具体聚合角色,实现迭代器接口,并需要私有字段记录遍历中的当前位置。
  • 聚集(Aggregate) 依赖迭代器角色,定义获得迭代器的接口。
  • 具体聚集(Concrete Aggregate) 实现聚合角色接口,私有字段:需要遍历的集合;共有方法:集合的数量和集合的索引

代码结构

	public static class IteratorApp
	{
		public static void Run()
		{
			ConcreteAggregate a = new ConcreteAggregate();

			a[0] = "Item A";
			a[1] = "Item B";
			a[2] = "Item C";
			a[3] = "Item D";

			Iterator i = a.CreateIterator();

			Console.WriteLine("Iterating over collection");

			object item = i.Firest();
			while (item != null)
			{
				Console.WriteLine(item);
				item = i.Next();
			}
		}
	}

	abstract class Aggregate
	{
		public abstract Iterator CreateIterator();
	}

	class ConcreteAggregate : Aggregate
	{
		private ArrayList _items = new ArrayList();

		public override Iterator CreateIterator()
		{
			return new ConcreteIterator(this);
		}

		public int Count
		{
			get { return _items.Count; }
		}

		public object this[int index]
		{
			get { return _items[index]; }
			set { _items.Insert(index, value); }
		}

	}

	abstract class Iterator
	{
		public abstract object Firest();
		public abstract object Next();
		public abstract bool IsDone();
		public abstract object CurrentItem();
	}

	class ConcreteIterator : Iterator
	{
		private ConcreteAggregate _aggregate;
		private int _current = 0;

		public ConcreteIterator(ConcreteAggregate aggregate)
		{
			this._aggregate = aggregate;
		}

		public override object CurrentItem()
		{
			return _aggregate[_current];
		}

		public override object Firest()
		{
			return _aggregate[0];
		}

		public override bool IsDone()
		{
			return _current >= _aggregate.Count;
		}

		public override object Next()
		{
			object ret = null;
			if (_current < _aggregate.Count - 1)
			{
				ret = _aggregate[++_current];
			}

			return ret;
		}
	}

情景案例

迭代器这种模式比较常见,主要是遍历集合。在C#中实现IEnumerable IEnumerable<out T>接口的都是可遍历的集合,而且可以通过语法糖foreach遍历。

	public static class IteratorRealWorld
	{
		public static void RunApp()
		{
			Friend friend = new Friend();
			FriendCollection friendcollection = friend.GetAllFriends();
			foreach (Friend f in friendcollection)
			{
				Console.WriteLine(f.Name);
			}
		}
	}

	public class Friend
	{
		public string Name { get; set; }
		public FriendCollection GetAllFriends()
		{
			return new FriendCollection(new Friend[]
			{
				new Friend(){Name ="关羽"},
				new Friend(){Name ="张飞"},
				new Friend(){Name ="赵云"},
				new Friend(){Name ="黄忠"},
				new Friend(){Name ="马超"}
			});
		}
	}

	public class FriendCollection : IEnumerable<Friend>
	{
		private Friend[] _friendArray;

		public FriendCollection(Friend[] friend)
		{
			this._friendArray = friend;
		}
		public Friend this[int index]
		{
			get { return _friendArray[index]; }
		}
		public int Count
		{
			get { return _friendArray.Length; }
		}

		public IEnumerator<Friend> GetEnumerator()
		{
			return new FriendIterator(this);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return new FriendIterator(this);
		}
		//为内部类
		public class FriendIterator : IEnumerator<Friend>
		{
			private readonly FriendCollection friends;
			private int index;

			public FriendIterator(FriendCollection friends)
			{
				this.friends = friends;
				index = -1;
			}

			public Friend Current
			{
				get { return this.friends[index]; }
			}

			public void Dispose()
			{
			}

			object IEnumerator.Current
			{
				get { return this.friends[index]; }
			}

			public bool MoveNext()
			{
				index++;
				if (index >= friends.Count)
				{
					return false;
				}
				else
				{
					return true;
				}
			}

			public void Reset()
			{
				index = -1;
			}
		}
	}
posted @ 2018-02-22 18:11  LoveTomato  阅读(449)  评论(0编辑  收藏