java设计模式-Iterator
Iterator模式
主要是用在容器的遍历上,其他的地方都不怎么用;理解一下,会用了就可以了;
1、背景
请动手自己写一个可以动态添加对象的容器;
代码:
ArrayList.java(是自己实现的,不是JDK)
package com.cy.dp.iterator; public class ArrayList { Object[] objects = new Object[10]; int index = 0; //objects下一个空的位置 /** * 如果数组容量已满,这里简单处理,扩容为原来的两倍; * sun的做法是有一个加权值,根据原来的容量,加上多少... * @param o */ public void add(Object o){ if(index == objects.length){ Object[] newObjects = new Object[objects.length * 2]; System.arraycopy(objects, 0, newObjects, 0, objects.length); objects = newObjects; } objects[index] = o; index++; } public int size(){ return index; } }
Cat.java 辅助类:
package com.cy.dp.iterator; public class Cat { private int id; public Cat(int id) { super(); this.id = id; } }
Test.java 测试类:
package com.cy.dp.iterator; import com.cy.dp.iterator.ArrayList; public class Test { public static void main(String[] args) { ArrayList al = new ArrayList(); for(int i=0; i<15; i++){ al.add(new Cat(i)); } System.out.println(al.size()); } }
2.上面容器的底层实现是用数组,下面使用链表来做个容器;
简单解释链表:
每一个链表里面装的都是一个一个的节点,每个节点里面包括两部分内容:1.数据本身 2.指向下一个节点的一个引用;
代码:
Node.java:
package com.cy.dp.iterator; public class Node { private Object data; private Node next; public Node(Object data, Node next) { super(); this.data = data; this.next = next; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } }
LinkedList.java:
package com.cy.dp.iterator; public class LinkedList { Node head = null; Node tail = null; //最末尾的节点 int size = 0; //记录当前链表里面Node个数 public void add(Object o){ Node n = new Node(o, null); if(head==null){ head = n; tail = n; } tail.setNext(n); tail = n; size++; } public int size(){ return size; } }
Test.java 测试类:
package com.cy.dp.iterator; import com.cy.dp.iterator.ArrayList; import com.cy.dp.iterator.LinkedList; public class Test { public static void main(String[] args) { //ArrayList al = new ArrayList(); LinkedList al = new LinkedList(); for(int i=0; i<15; i++){ al.add(new Cat(i)); } System.out.println(al.size()); } }
3.考虑容器的可替换性
Test类中的容器类可以替换,但是测试方法无须修改;比如LinkedList里面添加元素方法为addObject()的话,那么代码就要重新修改了;
所以有必要对ArrayList和LinkedList对外公开的方法统一起来;
使用接口Collection,面向接口编程;好处是灵活,可扩展;
于是就变成了代码:
Collection.java:
package com.cy.dp.iterator; public interface Collection { void add(Object o); int size(); }
ArrayList.java (实现Collection接口)
package com.cy.dp.iterator; import com.cy.dp.iterator.Collection; public class ArrayList implements Collection { Object[] objects = new Object[10]; int index = 0; //objects下一个空的位置 /** * 如果数组容量已满,这里简单处理,扩容为原来的两倍; * sun的做法是有一个加权值,根据原来的容量,加上多少... * @param o */ public void add(Object o){ if(index == objects.length){ Object[] newObjects = new Object[objects.length * 2]; System.arraycopy(objects, 0, newObjects, 0, objects.length); objects = newObjects; } objects[index] = o; index++; } public int size(){ return index; } }
LinkedList.java(实现Collection接口)
package com.cy.dp.iterator; import com.cy.dp.iterator.Collection; public class LinkedList implements Collection { Node head = null; Node tail = null; //最末尾的节点 int size = 0; //记录当前链表里面Node个数 public void add(Object o){ Node n = new Node(o, null); if(head==null){ head = n; tail = n; } tail.setNext(n); tail = n; size++; } public int size(){ return size; } }
Test.java测试类:
public class Test { public static void main(String[] args) { Collection c = new LinkedList(); for(int i=0; i<15; i++){ c.add(new Cat(i)); } System.out.println(c.size()); } }
4.容器的遍历
因为上面ArrayList的遍历方式和LinkedList的遍历方式不同,遍历方式不统一的话,实现方式一变,代码就得跟着变;
每一种容器都有自己的遍历方式,那么能不能找到一种统一的遍历方式呢?
代码:
Iterator接口:
package com.cy.dp.iterator; public interface Iterator { Object next(); boolean hasNext(); }
Collection接口:
package com.cy.dp.iterator; public interface Collection { void add(Object o); int size(); Iterator iterator(); }
ArrayList.java:
package com.cy.dp.iterator; import com.cy.dp.iterator.Collection; public class ArrayList implements Collection { Object[] objects = new Object[10]; int index = 0; //objects下一个空的位置 /** * 如果数组容量已满,这里简单处理,扩容为原来的两倍; * sun的做法是有一个加权值,根据原来的容量,加上多少... * @param o */ @Override public void add(Object o){ if(index == objects.length){ Object[] newObjects = new Object[objects.length * 2]; System.arraycopy(objects, 0, newObjects, 0, objects.length); objects = newObjects; } objects[index] = o; index++; } @Override public int size(){ return index; } @Override public Iterator iterator(){ return new ArrayListIterator(); } private class ArrayListIterator implements Iterator{ private int currentIndex = 0; @Override public Object next() { Object o = objects[currentIndex]; currentIndex++; return o; } @Override public boolean hasNext() { if(currentIndex >= index) return false; else return true; } } }
LinkedList.java:
package com.cy.dp.iterator; import com.cy.dp.iterator.Collection; public class LinkedList implements Collection { Node head = null; Node tail = null; //最末尾的节点 int size = 0; //记录当前链表里面Node个数 @Override public void add(Object o){ Node n = new Node(o, null); if(head==null){ head = n; tail = n; } tail.setNext(n); tail = n; size++; } @Override public int size(){ return size; } //返回一个实现了Iterator接口的匿名类 @Override public Iterator iterator(){ return new Iterator(){ Node currentNode = head; @Override public Object next() { Object o = currentNode.getData(); currentNode = currentNode.getNext(); return o; } @Override public boolean hasNext() { if(currentNode==null) return false; else return true; } }; } }
Test.java 测试类:
public class Test { public static void main(String[] args) { Collection c = new LinkedList(); //Collection c = new ArrayList(); for(int i=0; i<15; i++){ c.add(new Cat(i)); } System.out.println(c.size()); Iterator it = c.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
打印:
15 Cat [id=0] Cat [id=1] Cat [id=2] Cat [id=3] Cat [id=4] Cat [id=5] Cat [id=6] Cat [id=7] Cat [id=8] Cat [id=9] Cat [id=10] Cat [id=11] Cat [id=12] Cat [id=13] Cat [id=14]