Java设计模式之迭代器模式

Java设计模式之迭代器模式

 

        摘要:本篇笔记主要是记录迭代器模式的学习过程、其实只要是有点Java编程经验的人都知道这个设计模式、只是不一定能想起来这是四人组23中设计模式之一。迭代器模式(Iterator Pattern)、从名字中我们就知道在哪里见过他们、没错、我们经常使用的集合。既然使用集合就要提供一种能遍历集合的机制。这也是迭代器模式的作用。

 

一:简介

       

        这里主题是介绍迭代器模式、而迭代器一般就是在集合中使用的、所以结合集合的迭代特性来学习这种设计模式。

        通过对ArrayList、和LinkedList的学习来了解他的机制。我们可以仿照、可以自己实现自己的ArrayList、LinkedList、并对他们进行迭代来学习迭代器模式。下面是仿照JDK的集合来实现的。

 

二:问题的提出与解决

 

        我们先抛开JDK为我们实现的Iterator和集合。

        1、如何迭代自定义ArrayList?

        假设我们有一个集合类:ArrayList、他内部是通过数组来保存元素的、我们如何来迭代他其中的所有元素?相信这个不难、为简单起见——ArrayList代码:


package com.chy.dp.iterator;

public class ArrayList {
	Object[] objects = new Object[10];
	int index = 0;

	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;
	}
	
	public Object getIndex(int index){
		return objects[index];
	}
}

        2、新建一个测试类来迭代我们的ArrayList——Client代码:


package com.chy.dp.iterator;
public class Client {
	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());
		
		for (int i = 0; i < al.size(); i++) {
			System.out.print(al.getIndex(i) + " ");
		}
	}
}

        3、当我们又有一个LinkedList的时候、我们想迭代LinkedList又会有什么问题呢?——LinkedList代码:


package com.chy.dp.iterator;

public class Node {
	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;
	}
	private Object data;
	private Node next;
}


package com.chy.dp.iterator;

public class LinkedList {
	Node head = null;
	Node tail = null;
	int size = 0;

	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;
	}
}


        4、显然上面Client中的迭代方法肯定是不能迭代LinkedList!我们只能自己去实现LinkedList的迭代方法、而且必定与ArrayList实现方式不一样、那么当我们又存在别的集合的时候该怎么办?比如迭代TreeSet、HashSet、Hashtable等等。那么有没有一种方式是可以用来迭代所有集合的呢?不管他的类型是什么都可以?当然可以、既然我们要迭代一个集合、那么我们就可以为集合抽象出一个接口、在接口中定义一个获取当前集合的迭代所需要的迭代器——Iterator。这个迭代器需要子类去实现(因为不同的集合迭代的方式不同)、而迭代器需要提供hasNext、next两个方法、用来判断是否有下一个和获取下一个的方法。具体实现:

                a) 定义一个抽象集合接口——Collection代码:


package com.chy.dp.iterator;

public interface Collection {
	void add(Object o);

	int size();

	Iterator iterator();
}

                b) 定义一个迭代器——Iterator代码:


package com.chy.dp.iterator;

public interface Iterator {
	Object next();

	boolean hasNext();
}

               c)子类ArrayList实现Collection接口、并且提供获取Iterator的方法——ArrayList代码:


package com.chy.dp.iterator;

import com.chy.dp.iterator.Collection;
import com.chy.dp.iterator.Iterator;

public class ArrayList implements Collection {
	Object[] objects = new Object[10];
	int index = 0;

	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;
	}

	public Object getIndex(int index) {
		return objects[index];
	}

	public Iterator iterator() {

		return new ArrayListIterator();
	}

	private class ArrayListIterator implements Iterator {
		private int currentIndex = 0;

		@Override
		public boolean hasNext() {
			if (currentIndex >= index)
				return false;
			else
				return true;
		}

		@Override
		public Object next() {
			Object o = objects[currentIndex];
			currentIndex++;
			return o;
		}

	}
}

                d)子类LinkedList实现Collection接口、并且提供获取Iterator的方法——LinkedList代码:


package com.chy.dp.iterator;

import com.chy.dp.iterator.Collection;
import com.chy.dp.iterator.Iterator;

public class LinkedList implements Collection {
	Node head = null;
	Node tail = null;
	int size = 0;

	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;
	}

	@Override
	public Iterator iterator() {
		return new LinkedListIterator();
	}

	private class LinkedListIterator implements Iterator {

		@Override
		public boolean hasNext() {
			return false;
		}

		@Override
		public Object next() {
			return null;
		}
	}
}

                e)上面LinkedList的Iterator没有具体的实现、因为想说明的是这种设计模式、具体的实现可以自己弄弄看、或这看JDK的实现

                f那么此时我们就可以使用统一Iterator来迭代实现了Collection接口的所有类——Client代码:


package com.chy.dp.iterator;
import com.chy.dp.iterator.ArrayList;
public class Client {
	public static void main(String[] args) {
		Collection c = (Collection) 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()) {
			Object o = it.next();
			System.out.print(o + " ");
		}
	}
}

三:总结与补充

1、总结:

迭代器模式、是专门用与迭代集合元素的、当然也包括Map、从他们的整个结构图就能看出来、集合中所有的类都间接或者直接与Iterator、Iterable两个接口有关系。设计模式多了就会发现是似而非的感觉、因为设计模式的原则是不会变的、他们都是围绕着一个原则来设计的、最后的时候会补充设计模式围绕的设计原则。

2、补充:



更多内容:Java设计模式之起始






Java设计模式之迭代器模式,布布扣,bubuko.com

Java设计模式之迭代器模式

上一篇:JSON(03)C/C++处理JSON


下一篇:C++中的回调函数——指向类成员的指针