迭代器模式小试

迭代器是行为型设计模式的一种,是一种非常简单的设计模式。

转载请注明出处 http://www.cnblogs.com/zrtqsk/p/3716173.html,谢谢!

一、介绍

  先来看一下《研磨设计模式》的定义——提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

  迭代器模式的本质是——控制访问聚合对象中的元素

  Java中有的聚合对象主要是Collection类、Map类的各子类对象。同样的,数组也算一种聚合对象。迭代器模式就是希望从外部用同一种方式去访问不同的聚合对象。这个怎么做呢?

  说白了,就是创建一个迭代类,持有聚合对象,并且提供迭代这个聚合对象的方法。这个迭代类怎么得到呢?让原本的聚合对象增加一个方法,可以用来返回一个迭代对象,返回时,将自身传递给这个迭代对象。我们得到了这个迭代对象,就可以轻松的在外部访问这个聚合对象了。

 

二、我的实现

1、假设我们本身有一个包含简单功能的聚合类MyList,如下:

 1 public class MyList<T> {

 2 

 3     private Object[] elements;

 4     //容量

 5     private int capacity = 10;

 6     //当前大小

 7     private int size = 0;

 8     

 9     //指定容量的构造方法

10     public MyList(int capacity){

11         this.capacity = capacity;

12         elements = new Object[10];

13     }

14     

15     //默认构造方法

16     public MyList(){

17         this(10);

18     }

19     

20     public int size(){

21         return size;

22     }

23     

24     public T get(int i){

25         if(i > capacity){

26             System.out.println("List数组越界");

27             return null;

28         }else {

29             return (T) elements[i];

30         }

31     }

32     

33     public void add(T obj){

34         if(size >= capacity){

35             //扩容

36         }else {

37             elements[size ++] = obj;

38         }

39     }

40 }

2、测试一下:

 1 public class Test {

 2 

 3     public static void main(String[] args)

 4     {

 5         MyList<Apple> list = new MyList<Apple>();

 6         list.add(new Apple("a"));

 7         list.add(new Apple("b"));

 8         System.out.println(list.get(0));

 9         System.out.println(list.get(1));

10         System.out.println(list.get(3));

11     }

12 }

13 

14 class Apple{

15     private String name;

16     

17     public Apple(String name){

18         this.name = name;

19     }

20     

21     public String toString(){

22         return "Apple:" + name;

23     }

24     

25 }

3、结果如下:

Apple:a

Apple:b

List数组越界

null

可见功能正常。

4、我们需要从外部访问这个聚合对象,该怎么做呢?

如前面说的,写一个简单的访问数据的接口,包含简单的迭代聚合对象的功能如下:

1 public interface Iterator<T> {

2     

3     public T next();

4     

5     public boolean hasNext();

6 }

5、简单的实现类;

 1 public class IteratorImpl<T> implements Iterator<T> {

 2 

 3     private int index = 0;

 4     MyList list = null;

 5     public IteratorImpl(MyList list){

 6         this.list = list;

 7     }

 8 

 9     @Override

10     public T next()

11     {

12         return (T) list.get(index++);

13     }

14 

15     @Override

16     public boolean hasNext()

17     {

18         boolean flag = false;

19         if(list.get(index) != null){

20             flag = true;

21         }

22         return flag;

23     } 

24 }

6、构建一个简单的抽象类AbstractList,而实际上List的大部分方法都可以放到这个抽象类来,这里为了演示方便,如下:

1 public abstract class AbstractList {

2 

3     public abstract Iterator iterator();

4 }

7、刚才的MyList继承这个抽象类,其实现方法如下:

1 @Override

2     public Iterator iterator()

3     {

4         return new IteratorImpl(this);

5     }

非常简单!

8、下面我们就是测试,测试类比之前改变一点点,如下;

 1 public class Test {

 2 

 3     public static void main(String[] args)

 4     {

 5         MyList<Apple> list = new MyList<Apple>();

 6         list.add(new Apple("a"));

 7         list.add(new Apple("b"));

 8 //        System.out.println(list.get(0));

 9 //        System.out.println(list.get(1));

10 //        System.out.println(list.get(3));

11         Iterator it = list.iterator();

12         while(it.hasNext()){

13             System.out.println(it.next());

14         }

15     }

16 }

9,结果如下:

Apple:a

Apple:b

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

 

三、Java的迭代器

  通常而言,我们遍历一个聚合对象除了使用Iterator外,还有一种更简便的方法,那就是用简易的for循环——for(Type t : Collection)。但是当我们用这个方式去访问上文我自定义的聚合对象MyList的时候,发现编译错误。错误提示说,因为我们没有实现java.lang.Iterable接口。  这个接口位于java.lang包下,意味着我们不用额外导包了。我们来看一下这个接口的源代码:

package java.lang;



import java.util.Iterator;



public interface Iterable<T> {



    Iterator<T> iterator();

}

可见,这个接口只有一个方法,用来返回一个java.util.Iterator接口对象。相当于我们刚才的抽象类。

  Java的迭代器实现主要就是围绕着这两个接口,我们来看一下java.util.Iterator的源代码

package java.util;



public interface Iterator<E> {



    boolean hasNext();



    E next();



    void remove();

}

可以看到,这个接口是非常简单的。跟上面我自定义的Iterator相比,只是多了一个void remove()方法。

  下面我们将上面的例子改为Java的迭代器实现。通常而言,由于一个Iterator的实现类是对应一个聚合对象的。为了提高内聚性,我们应该将Iterator实现类作为聚合对象的内部类。而JDK也是这么做的。如下:

 1 import java.util.Iterator;

 2 

 3 //实现Iterable接口

 4 public class MyList<T> implements Iterable<T>{

 5 

 6     private Object[] elements;

 7     // 容量

 8     private int capacity = 10;

 9     // 当前大小

10     private int size = 0;

11 

12     // 指定容量的构造方法

13     public MyList(int capacity)

14     {

15         this.capacity = capacity;

16         elements = new Object[10];

17     }

18 

19     // 默认构造方法

20     public MyList()

21     {

22         this(10);

23     }

24 

25     public int size()

26     {

27         return size;

28     }

29 

30     public T get(int i)

31     {

32         if (i > capacity)

33         {

34             System.out.println("List数组越界");

35             return null;

36         }

37         else

38         {

39             return (T) elements[i];

40         }

41     }

42 

43     public void add(T obj)

44     {

45         if (size >= capacity)

46         {

47             // 扩容

48         }

49         else

50         {

51             elements[size++] = obj;

52         }

53     }

54 

55     //返回java.util.Iterator对象

56     @Override

57     public Iterator iterator()

58     {

59         return new IteratorImpl(this);

60     }

61 

62     //内部类

63     class IteratorImpl<T> implements Iterator<T> {

64 

65         private int index = 0;

66         MyList list = null;

67 

68         public IteratorImpl(MyList list)

69         {

70             this.list = list;

71         }

72 

73         @Override

74         public T next()

75         {

76             return (T) list.get(index++);

77         }

78 

79         @Override

80         public boolean hasNext()

81         {

82             boolean flag = false;

83             if (list.get(index) != null)

84             {

85                 flag = true;

86             }

87             return flag;

88         }

89 

90         @Override

91         public void remove()

92         {

93             

94         }

95     }

96 }

同时,我们还可以使用简易for循环迭代这个聚合对象,如下:

 1 public class Test {

 2 

 3     public static void main(String[] args)

 4     {

 5         MyList<Apple> list = new MyList<Apple>();

 6         list.add(new Apple("a"));

 7         list.add(new Apple("b"));

 8 //        System.out.println(list.get(0));

 9 //        System.out.println(list.get(1));

10 //        System.out.println(list.get(3));

11         Iterator it = list.iterator();

12         for(Apple a : list ){

13             System.out.println(a);

14         }

15     }

16 }

结果与之前没有什么不同。

 

 

 

 

你可能感兴趣的:(迭代器模式)