反覆器模式-Iterator Pattern

設計模式系列

目的:提供方法走訪集合內的物件,走訪過程不需知道集合內部結構。

而在C#中,使用foreach語法本身就可以算是在使用Iterator Pattern了。

使用時機:

  1. 需要訪問一個聚合物件內容,而無須暴露內部。
  2. 需要支援聚合物件的多種反覆。
  3. 需要不同的聚合結構提供一個統一介面。
    class Program
    {
        static void Main(string[] args)
        {
            ConcreteAggregate a = new ConcreteAggregate();
            a[0] = "大鳥";
            a[1] = "小菜";
            a[2] = "行李";
            a[3] = "老外";
            a[4] = "公交內部員工";
            a[5] = "小偷";

            Iterator i = new ConcreteIterator(a);
            while (!i.IsDone())
            {
                Console.WriteLine($"{i.CurrentItem()}請買車票!");
                i.Next();
            }
        }
    }

    abstract class Iterator
    {
        public abstract object First();

        public abstract object Next();

        public abstract bool IsDone();

        public abstract object CurrentItem();
    }


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

    class ConcreteAggregate:Aggregate
    {
        private IList<object> items = new List<object>();
        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);}
        }
    }

    class ConcreteIterator:Iterator
    {
        private ConcreteAggregate aggregate;
        private int current = 0;

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

        public override object First()
        {
            return aggregate[0];
        }

        public override object Next()
        {
            object ret = null;
            current++;
            if (current < aggregate.Count)
            {
                ret = aggregate[current];
            }

            return ret;
        }
        public override object CurrentItem()
        {
            return aggregate[current];
        }
        public override bool IsDone()
        {
            return current >= aggregate.Count ? true : false;
        }
   
    }

    class ConcreteIteratorDesc:Iterator
    {
        private ConcreteAggregate aggregate;
        private int current = 0;

        public ConcreteIteratorDesc(ConcreteAggregate aggregate)
        {
            this.aggregate = aggregate;
            current = aggregate.Count - 1;
        }

     

        public override object First()
        {
            return aggregate[aggregate.Count - 1];
        }

        public override object Next()
        {
            object ret = null;
            current--;
            if (current >= 0) {
                ret = aggregate[current];
            }
            return ret;
        }
        public override object CurrentItem()
        {
            return aggregate[current];
        }
        public override bool IsDone()
        {
            return current < 0 ? true : false;
        }

    }

缺點:遍歷的同時更改迭代器所在的集合結構會導致出現異常,只能使用foreach對集合進行遍歷,不能在遍歷的同時更改集合中的元素。 

元哥的筆記