2013年10月4日 星期五

設計模式 (六) Iterator Pattern

Iterator Pattern 為反覆器讓我們能夠取得collection內的元素(string)而不需要取得collection (List<string>,string[]) 這樣的好處讓我們可以將這些元素  一視同仁(printDevice)
讓我們方便處理

下面的sample  我們希用使用printDevice 去印出Ted 和 Paul身上的配件
但是他們兩個是使用不同的collection  Ted是使用List<string>  而 Paul是使用string[]
通常都會使用以下的寫法
 
      

        class Ted_Devices

        {

            private List<string> items = new List<string>();

            public Ted_Devices()

            {

                items.Add("Phone");

                items.Add("Bag");

                items.Add("Pad");

            }

            public List<string> GetItems()

            {

                return items;

            }

        }

        class Paul_Devices

        {

            private string[] items = new string[3];

            public Paul_Devices()

            {

                items[0]="Pencil";

                items[1]="Watch";

                items[2]="book";

            }

            public string[] GetItems()

            {

                return items;

            }

        }

        static void Main(string[] args)

        {

            Ted_Devices TD = new Ted_Devices();

            List<string> TD_list = TD.GetItems();

            Paul_Devices PD = new Paul_Devices();

            string[] PD_list = PD.GetItems();

            Console.WriteLine("===Ted list====");

            printDevice(TD_list);

            Console.WriteLine("====Paul list====");

            printDevice(PD_list);

            Console.ReadLine();

        }



        private static void printDevice(object obj)

        {

            if (obj is List<string>)

            {

                foreach (string item in obj as List<string>)

                {

                    Console.WriteLine(item);

                }

            }

            else

            {

                foreach (string item in obj as string[])

                {

                    Console.WriteLine(item);

                }

            }

        }
Result:
===Ted list====
Phone
Bag
Pad
====Paul list====
Pencil
Watch
book
這樣的缺點是
當需要印更多人的裝置而每個人使用的collection的格式都不同時
例如出現了 int[] , List<CustomData>, ....等等的資料時
printDevice 就會長的越來越可怕  判斷式越來越多
如果這時出現新的需求不是只需要印device
還需要針對每個人身上的配件去做其他項目的處理時....
這樣的code就會變的非常難以maintain以及新增功能

下面的寫法是使用Iterator的方式

public interface Iterator
    {
        bool hasNext();
        Object next();
    }
    class TedIterator : Iterator
    {
        private List<string> items;
        int position = 0;
        public TedIterator(List<string> items)
        {
            this.items = items;
        }
        public bool hasNext()
        {
            if (position &gt;= items.Count)
                return false;
            else
                return true;
        }

        public object next()
        {
            string CurrentItem = items[position];
            position++;
            return CurrentItem;
        }
    }
    class Ted_Devices
    {
        private List<string> items = new List<string>();
        public Ted_Devices()
        {
            items.Add("Phone");
            items.Add("Bag");
            items.Add("Pad");
        }
        public Iterator CreateIterator()
        {
            return new TedIterator(items);
        }
    }
    class PaulIterator : Iterator
    {
        private string[] items;
        int position = 0;
        public PaulIterator(string[] items)
        {
            this.items = items;
        }
        public bool hasNext()
        {
            if (position &gt;= items.Length || items[position]==null)
                return false;
            else
                return true;
        }

        public object next()
        {
            string CurrentItem = items[position];
            position++;
            return CurrentItem;
        }
    }
    class Paul_Devices
    {
        private string[] items = new string[3];
        public Paul_Devices()
        {
            items[0] = "Pencil";
            items[1] = "Watch";
            items[2] = "book";
        }
        public Iterator CreateIterator()
        {
            return new PaulIterator(items);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Ted_Devices TD = new Ted_Devices();
            Iterator TD_list = TD.CreateIterator();
            Paul_Devices PD = new Paul_Devices();
            Iterator PD_list = PD.CreateIterator();
            Console.WriteLine("===Ted list====");
            printDevice(TD_list);
            Console.WriteLine("====Paul list====");
            printDevice(PD_list);
            Console.ReadLine();
        }

        private static void printDevice(Iterator obj)
        {
            while (obj.hasNext())
            {
                Console.WriteLine(obj.next());
            }
        }
    }
Result:
===Ted list====
Phone
Bag
Pad
====Paul list====
Pencil
Watch
book
從Main function就可以很清楚的看到  兩個人的collection  List<string> 和 string[]都被轉為iterator
若有需要對data做進一步的處理  他們可以使用相同的寫法(printDevice) 去印出他們身上的device
若有進一步的處理  也可以使用同樣一套寫法 (不需要用if else去區分是誰的device)
這樣子在maintain以及開發上就會相對輕鬆許多

沒有留言:

張貼留言