迭代器是行为型设计模式的一种,是一种非常简单的设计模式。
转载请注明出处 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 }
结果与之前没有什么不同。