频道栏目
首页 > 资讯 > Java > 正文

迭代器模式小试

14-05-09        来源:[db:作者]  
收藏   我要投稿
一、介绍
 
  先来看一下《研磨设计模式》的定义——提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
 
  迭代器模式的本质是——控制访问聚合对象中的元素
 
  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 {
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 }
复制代码
结果与之前没有什么不同。
相关TAG标签
上一篇:Cocos2d-x for Windows Phone 用法总结
下一篇:C++名字空间/C++命名空间
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站