C#設計模式系列:迭代器模式(Iterator)

libingql發表於2014-04-01

  迭代器模式把物件的職責分離,職責分離可以最大限度減少彼此之間的耦合程度,從而建立一個鬆耦合的物件。職責分離的要點是對被分離的職責進行封裝,並以抽象的方式建立彼此之間的關係。

1、迭代器模式簡介

1.1>、定義

  迭代器模式提供一種方法可以順序訪問聚合物件中各個元素,但又不暴露該物件的內部表示。

1.2>、使用頻率

  

2、迭代器模式結構

2.1>、結構圖

2.2>、參與者

  迭代器模式參與者:

  ◊ Iterator:迭代器定義訪問和遍歷元素的介面

  ◊ ConcreteIterator

    ° 具體迭代器實現迭代器介面

    ° 對該聚合遍歷時跟蹤當前位置

  ◊ Aggregate:聚合定義建立Iterator物件的介面

  ◊ ConcreteAggregate:具體聚合,實現相應迭代器的介面,返回具體迭代器的一個適當的例項。

  在迭代器模式中,ConcreteAggregate通過Aggregate定義的介面得到Iterator,並且這是一個ConcreteIterator,該ConcreteIterator具體實現了對ConcreteAggregate的訪問與遍歷的方法。通過ConcreteIterator可以訪問並使用集合中的元素。

3、迭代器模式結構實現

  Iterator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Structural
{
    public abstract class Iterator
    {
        public abstract object First();
        public abstract object Next();
        public abstract bool IsDone();
        public abstract object CurrentItem();
    }
}

  Aggregate.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Structural
{
    public abstract class Aggregate
    {
        public abstract Iterator CreateIterator();
    }
}

  ConcreteAggregate.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;

namespace DesignPatterns.IteratorPattern.Structural
{
    public 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); }
        }
    }
}

  ConcreteIterator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Structural
{
    public 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;
            if (_current < _aggregate.Count - 1)
            {
                ret = _aggregate[++_current];
            }

            return ret;
        }

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

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

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.IteratorPattern.Structural;

namespace DesignPatterns.IteratorPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            ConcreteAggregate a = new ConcreteAggregate();
            a[0] = "Item A";
            a[1] = "Item B";
            a[2] = "Item C";
            a[3] = "Item D";

            ConcreteIterator i = new ConcreteIterator(a);

            Console.WriteLine("Iterating over collection:");
            object item = i.First();
            while (item != null)
            {
                Console.WriteLine(item);
                item = i.Next();
            }
        }
    }
}

  執行輸出:

Iterating over collection:
Item A
Item B
Item C
Item D
請按任意鍵繼續. . .

4、迭代器模式實踐應用

  在迭代器模式的設計中,有兩種具體的實現方式,分別為外稟迭代器和內稟迭代器。白箱聚集與外稟迭代器:白箱聚集向外界提供訪問自己內部元素的介面,從而使得外稟迭代器可以通過聚集提供的方法實現迭代功能。黑箱聚集與內稟迭代器:黑箱聚集不向外界提供遍歷自己內部元素的介面,因此聚集的成員只能被聚集內部的方法訪問。由於內稟迭代器恰好也是聚集的成員,因此可以訪問聚集元素。

4.1、外稟迭代器

  外稟迭代器的迭代過程使用了集合中的元素,通過集合向外界提供了訪問自身內部元素的機會。

  Iterator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator
{
    /// <summary>
    /// 定義一個迭代器介面
    /// </summary>
    public interface Iterator
    {
        /// <summary>
        /// 迭代器定位到聚合的第一個元素
        /// </summary>
        void First();

        /// <summary>
        /// 遍歷下一個
        /// </summary>
        void Next();

        /// <summary>
        /// 判斷是否完成遍歷
        /// </summary>
        /// <returns></returns>
        bool IsDone();

        /// <summary>
        /// 獲得當前遍歷的項
        /// </summary>
        /// <returns></returns>
        object CurrentItem();
    }
}

  ConcreteIterator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator
{
    /// <summary>
    /// 定義具體的迭代器類
    /// </summary>
    public class ConcreteIterator : Iterator
    {
        private ConcreteAggregate aggregate;
        private int index = 0;
        private int size = 0;

        /// <summary>
        /// 根據不同的聚合類進行初始化
        /// </summary>
        /// <param name="aggregate"></param>
        public ConcreteIterator(ConcreteAggregate aggregate)
        {
            this.aggregate = aggregate;
            size = aggregate.Size();
            index = 0;
        }

        public void First()
        {
            index = 0;
        }

        public void Next()
        {
            if (index < size)
            {
                index++;
            }
        }

        /// <summary>
        /// 判斷是否遍歷完畢
        /// </summary>
        /// <returns></returns>
        public bool IsDone()
        {
            return index >= size;
        }

        /// <summary>
        /// 獲取當前遍歷的元素
        /// </summary>
        /// <returns></returns>
        public object CurrentItem()
        {
            return aggregate.GetElement(index);
        }
    }
}

  Aggregate.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator
{
    /// <summary>
    /// 定義一個抽象的聚合類
    /// </summary>
    public abstract class Aggregate
    {
        /// <summary>
        /// 只有一個功能,建立迭代器
        /// </summary>
        /// <returns></returns>
        public virtual Iterator CreateIterator()
        {
            return null;
        }
    }
}

  ConcreteAggregate.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator
{
    /// <summary>
    /// 定義一個具體的聚合類
    /// </summary>
    public class ConcreteAggregate : Aggregate
    {
        // 儲存元素的集合
        private object[] objs = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

        /// <summary>
        /// 獲得元素個數
        /// </summary>
        /// <returns></returns>
        public int Size()
        {
            return objs.Length;
        }

        /// <summary>
        /// 獲取指定序號的元素
        /// </summary>
        /// <param name="index">指定的序號</param>
        /// <returns></returns>
        public object GetElement(int index)
        {
            if (index < 0 || index > objs.Length)
            {
                return null;
            }

            return objs[index];
        }

        /// <summary>
        /// 建立該聚合類的迭代器
        /// </summary>
        /// <returns></returns>
        public override Iterator CreateIterator()
        {
            return new ConcreteIterator(this);
        }
    }
}

  Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator
{
    public class Client
    {
        private Iterator _iterator;
        private Aggregate _aggregate = new ConcreteAggregate();

        public void Operation()
        {
            // 獲得迭代器
            _iterator = _aggregate.CreateIterator();

            while (!_iterator.IsDone())
            {
                Console.WriteLine(_iterator.CurrentItem());
                _iterator.Next();
            }
        }

        static void Main(string[] args)
        {
            Client client = new Client();
            client.Operation();
        }
    }
}

  執行輸出:

Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
請按任意鍵繼續. . .

4.2、內稟迭代器

  內稟迭代器實現的關鍵是在集合的內部定義一個私有的具體迭代子類,由它來負責迭代器的所有功能。因為它是集合的私有類,所以它的物件可以遍歷集合的內部元素,實現迭代器定義的所有介面,而集合本身並未向外界提供訪問自己內部元素的介面。

  Iterator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.IntrinsicIterator
{
    /// <summary>
    /// 定義一個迭代器介面
    /// </summary>
    public interface Iterator
    {
        /// <summary>
        /// 迭代器定位到聚合的第一個元素
        /// </summary>
        void First();

        /// <summary>
        /// 遍歷下一個
        /// </summary>
        void Next();

        /// <summary>
        /// 判斷是否完成遍歷
        /// </summary>
        /// <returns></returns>
        bool IsDone();

        /// <summary>
        /// 獲得當前遍歷的項
        /// </summary>
        /// <returns></returns>
        object CurrentItem();
    }
}

  Aggregate.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.IntrinsicIterator
{
    /// <summary>
    /// 定義一個抽象的聚合類
    /// </summary>
    public abstract class Aggregate
    {
        /// <summary>
        /// 只有一個功能,建立迭代器
        /// </summary>
        /// <returns></returns>
        public virtual Iterator CreateIterator()
        {
            return null;
        }
    }
}

  ConcreteAggregate.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.IntrinsicIterator
{
    /// <summary>
    /// 定義一個具體的聚合類
    /// </summary>
    public class ConcreteAggregate : Aggregate
    {
        // 儲存元素的集合
        private static object[] objs = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

        /// <summary>
        /// 定義具體的迭代器類
        /// </summary>
        private class ConcreteIterator : Iterator
        {
            private int _index = 0;

            public void First()
            {
                _index = 0;
            }

            public void Next()
            {
                if (_index < objs.Length)
                {
                    _index++;
                }
            }

            public bool IsDone()
            {
                return _index == objs.Length;
            }

            public object CurrentItem()
            {
                return objs[_index];
            }
        }

        /// <summary>
        /// 獲得元素個數
        /// </summary>
        /// <returns></returns>
        public int Size()
        {
            return objs.Length;
        }

        /// <summary>
        /// 獲取指定序號的元素
        /// </summary>
        /// <param name="index">指定的序號</param>
        /// <returns></returns>
        public object GetElement(int index)
        {
            if (index < 0 || index > objs.Length)
            {
                return null;
            }

            return objs[index];
        }

        /// <summary>
        /// 建立該聚合類的迭代器
        /// </summary>
        /// <returns></returns>
        public override Iterator CreateIterator()
        {
            return new ConcreteIterator();
        }
    }
}

  Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.IteratorPattern.Practical.IntrinsicIterator
{
    public class Client
    {
        private Iterator _iterator;
        private Aggregate _aggregate = new ConcreteAggregate();

        public void Operation()
        {
            // 獲得迭代器
            _iterator = _aggregate.CreateIterator();

            while (!_iterator.IsDone())
            {
                Console.WriteLine(_iterator.CurrentItem());
                _iterator.Next();
            }
        }

        static void Main(string[] args)
        {
            Client client = new Client();
            client.Operation();
        }
    }
}

5、迭代器模式應用分析

  迭代器模式適用情形:

  1>、訪問一個具體物件的內容而不暴露它的內部表示;

  2>、支援對聚合物件的多種遍歷;

  3>、為遍歷不同的聚合結構提供一個統一的介面(即支援多型迭代)。

  迭代器模式特點:

  1>、簡化聚集的行為,迭代器具備了遍歷的介面,這樣聚集的介面就不必具備遍歷介面;

  2>、每一個聚集物件都可以有一個或者更多的迭代器物件,每一個迭代器的迭代狀態可以彼此獨立(外稟迭代器);

  3>、遍歷演算法被封裝到迭代器物件中,迭代演算法可以獨立於聚集物件變化。Client不必知道聚集物件的型別,通過迭代器可以就讀取和遍歷聚集物件。這樣的好處是聚集本身內部資料發生變化而不影響Client的程式。

相關文章