解讀設計模式----迭代器模式(Iterator Pattern)

1、你在開發中使用過迭代嗎?
     當你在使用JavaScript開發客戶端應用的時候使用過for...in嗎?
 javascript

 1 < script type = " text/javascript " >
 2 var  obj;
 3 useForIn  =   function  ()
 4 {
 5   obj = (0,1,2,3,4,5,6,7,8,9);
 6   for(var o in obj)
 7   {
 8      document.write(o);
 9   }

10}

11 < / script>
 
      當你在.NET Frameworks上使用C#,VB.NET,等語言開發應用的時候使用過foreach....in嗎?
 
 1 class  Program
 2 {
 3    static void Main(string[] args)
 4    {
 5        List<int> list = new List<int>();
 6        //--------初始化集合-----------
 7        for (int i = 0; i < 10; i++)
 8        {
 9            list.Add(i);
10        }

11        //-------遍歷集合--------------
12        foreach (int i in list)
13        {
14            Console.WriteLine(i);
15        }

16    }

17}

     若是你是一位Java發燒者,你在遍歷集合的時候是使用什麼方式呢?是 Iterator?仍是for?
 
 1 import  java.util. * ;
 2 public   class  UseForIn  {
 3    public static void main(String[] args) {
 4        List<String> list = new ArrayList<String>();
 5        for (int i = 0; i < 10; i++{
 6            list.add("String:" + i);
 7        }

 8        //--------------使用Iterator遍歷集合---------------
 9        Iterator it = list.iterator();
10        while(it.hasNext()){
11            System.out.println(it.next());
12        }

13        //------使用for.in(JDK 1.5以更高版本才能支持)-----
14        
15        for (String s : list ){
16            System.out.println(s);
17        }

18    }

19}
 
2、解說迭代模式
     咱們先來看看迭代器模式的UML圖(下圖來至 [url]http://www.dofactory.com/[/url])
        
迭代器模式(Iterator)
迭代器模式(Iterator),提供一種方法順序訪問一個集合對象中的各個元素,而不暴露該對象的內部表示。


        能夠說,.NET Frameworks中的每個集合對象,都應用了Iterator模式。一個彙集對象,並且無論這些對象是何時都須要遍歷的時候,咱們都應該使用迭代器模式。另外在咱們須要爲集合對象提供多種遍歷方式的時候也能夠考慮用迭代器模式。

        原本這個模式仍是頗有意思的,不過現今來看迭代器模式實用價格遠不如學習價值大了。由於如今的高級編程語言如C#,Java等自己已經把這個模式作在語言中了。回到本文開始,我想你就可以明白我爲何在文章的開始部分就發起提問?就拿C#的foreach....in語言來講吧,他就是一個能夠遍歷全部的集合對象的工具,並且很是好用。

        另外還有像IEnumerable接口也是爲迭代器模式而準備的,無論如何,學習一下GOF的迭代器模式的基本結構,仍是頗有學習價值的。研究歷史是爲了更好地迎接將來(這句話是Copy一本設計模式的書上,我一下忘了,若有知道的能夠在下面留言告訴下)。

3、悟透foreach....in語句
        爲了使用戶更方便的遍歷集合對象的全部元素,C#提供了foreach...in語句,該語句的實現正是經過IEnumerable的MoveNext()來完成遍歷的。
        爲了驗證foreach....in語句與迭代器的關係,咱們來定義一個實現逆序遍歷集合的類ReverseList類,定義很簡單,只須要繼承ArrayList類,並重寫GetEnumerator方法既可。
 
 1 namespace  DesignPattern.Iterator
 2 {
 3    public class ReverseList:ArrayList
 4    {
 5        public override IEnumerator GetEnumerator()
 6        {
 7            return new ReverseListEnumerator(this);
 8        }

 9    }

10}

    其中,類ReverseListEnumerator實現了IEnumerator,它提供了逆序遍歷的迭代器。定義以下:
 
 1 using  System;
 2 using  System.Collections.Generic;
 3 using  System.Text;
 4 using  System.Collections;
 5
 6 namespace  DesignPattern.Iterator
 7 {
 8    public class ReverseListEnumerator:IEnumerator
 9    {
10        public ReverseListEnumerator(ArrayList list)
11        {
12            this.list = list;
13            this.index = list.Count;
14            this.CurrentElement = list;
15        }

16
17        private object CurrentElement;
18        private int index;
19        private ArrayList list;
20
21        public object Current
22        {
23            get 
24            {
25                object obj = this.CurrentElement;
26                if (obj != this.list)
27                {
28                    return obj;
29                }

30                if (this.index == -1)
31                {
32                    throw new Exception("索引超出下標範圍!");
33                }

34            }

35        }

36
37        public bool MoveNext()
38        {
39            if (this.index > 0)
40            {
41                this.index--;
42                this.CurrentElement = this.list[this.index];
43                return true;
44            }

45            this.CurrentElement = this.list;
46            this.index = 0;
47            return false;
48        }

49
50        public void Reset()
51        {
52            this.CurrentElement = this.list;
53            this.index = this.list.Count;
54        }

55    }

56}

57

     咱們來比較下使用ArrayList和自定義的ReverseList類經過foreach....in遍歷後的結果:
 
 1 using  System;
 2 using  System.Collections.Generic;
 3 using  System.Text;
 4
 5 namespace  DesignPattern.Iterator
 6 {
 7    class Program
 8    {
 9        static void Main(string[] args)
10        {
11            List<int> list = new List<int>();
12            ReverseList rlist = new ReverseList();
13            //--------初始化數據-----------------------
14            for (int i = 0; i < 10; i++)
15            {
16                list.Add(i);
17                rlist.Add(i);
18            }

19            //-----使用C#的foreach.in語句(順序遍歷類ArrayList)-------
20            foreach (int i in list)
21            {
22                Console.Write(i + " ");
23            }

24            Console.WriteLine();  //起換行做用
25
26            //--------使用自定義的逆序遍歷類(ReverseList)--------------
27            foreach (int i in rlist)
28            {
29                Console.Write(i + " ");
30            }

31            Console.WriteLine();  //起換行做用
32        }

33    }

34}
 
運行結果以下:

 
4、現實生活中的迭代高手
     我想對於大多數(有一部分人本身有車,有部分人騎自行車或摩托車,有部分人步行)的人來講,天天都有這樣的經歷,早晨起牀後一陣忙碌,忙完了就是準備上班了。來到了公交車站,XX分鐘過去後,到上班點的公交來了,這時該作什麼?上貝,不上你就等着上班遲到吧,哈哈。
     仔細觀察售票員就會發現,每到一個站點,公交車都會停下上客或是下客,人多混雜(有的是買過票的,有的還沒買過),我真佩服售票員的記憶,乘客隨時都在上下,他老是能記住上了那些人,其中那些又是沒有買票的。他能夠從車頭賣票到車尾,也能夠從車尾到車頭,也能夠就在車門那站着售票,呵呵,這好象也迭代器有很大的聯繫。看看下面代碼:
 
1 public   class  公交車:ArrayList
2 {
3    
4}

     直接繼承ArrayList,什麼也不作,這時[公交車]也就擁有了ArrayList的公開屬性和方法。下面是[乘客類];
 
 1 using  System;
 2 using  System.Collections.Generic;
 3 using  System.Text;
 4
 5 namespace  DesignPattern.Iterator
 6 {
 7    public class 乘客
 8    {
 9        public 乘客() { }
10        public 乘客(string name, bool flag)
11        {
12            this.name = name;
13            this.flag = flag;
14        }

15
16        private string name;
17        public string Name
18        {
19            get return name; }
20            set { name = value; }
21        }

22
23        private bool flag;
24        public bool Flag
25        {
26            get return flag; }
27            set { flag = value; }
28        }

29    }

30}

    乘客名字和標識(是否買過票),看看下面的示例;
 
 1 namespace  DesignPattern.Iterator
 2 {
 3    class Program
 4    {
 5        static void Main(string[] args)
 6        {
 7            公交車 gjc = new 公交車();
 8            乘客 ck = null;
 9            //乘客上車
10            for (int i = 0; i < 5; i++)
11            {
12                ck = new 乘客(i + 1 + "號乘客"false);
13                gjc.Add(ck);
14            }

15            //迭代高手出場--收車費--所有收完
16            for (int i = 0; i < gjc.Count; i++)
17            {
18                乘客 c = (乘客)gjc[i];
19                c.Flag = true;
20            }

21            //到了一站--張三和李四上了車
22            //售票員還沒來收張三的錢呢,不會是在考驗張三是否是自覺掏錢買票吧
23            gjc.Add(new 乘客("張三"false));
24            gjc.Add(new 乘客("李四"true)); //這人老實,一上車就自動購票
25
26            foreach (乘客 k in gjc)
27            {
28                if (k.Flag)
29                {
30                    Console.WriteLine("到終點站了,{0}請下車!", k.Name);
31                }

32                if (!k.Flag)
33                {
34                    Console.WriteLine("你好{0}同志,你尚未買票,要走能夠,請先買票!", k.Name);
35                }

36            }

37        }

38    }

39}

     上面的代碼很簡單,我就不作詳細解說,運行結果以下圖:
      

5、總結迭代高手
        從上面的幾個示例中就能夠看出,儘管咱們沒有顯示的引用迭代器,但實質仍是經過迭代器來遍歷的。總地來講, 迭代器模式就是分離了集合對象的迭代行爲,抽象出一個迭代器類來負責,這樣既可作到不暴露集合的內部結構,又可讓外部代碼能夠透明的訪問集合內部的元素。         迭代器模式在訪問數組、集合、列表等數據時,尤爲是數據庫數據操做時,是很是廣泛的應用,但因爲它太廣泛了,因此各類高級語言都對他進行了封裝,因此反而給人感受此模式自己不太經常使用了。         看來現實生活中的售票員就是一位了不得的迭代高手,每次乘客上下車他都會數數進行統計,而後根據他本身的迭代方式去遍歷車內的乘客進行售票,不會放過任何逃票之客。         任何行業都有技巧和經驗,須要多思考、多琢磨,才能作到最好的。         編程又未嘗不是這樣,沒有最好,只有更好,咱們都須要努力。 注:上面總結源於《大話設計模式》  
相關文章
相關標籤/搜索