设计模式16 - Iterator 迭代器模式


1 Introduction


The Iterator pattern is one of the simplest and most frequently used of the design patterns. It allows you to move through a list or collection of data using a standard interface without having to know the details of that data's internal representations. You can also define special iterators that perform some special processing and return only specified elements of the data collection.


The Iterator pattern is useful because it provides a defined way to move through a set of data elements without exposing what is taking place inside the class. It is an interface; thus you can implement it in any way that is convenient for the data that you are returning. Design Patterns suggests that a suitable interface for an iterator might be the following:

public interface Iterator {
    public Object first();
    public Object next();
    public boolean isDone();
    public Object currentItem();
}

Using this interface, you can move to the top of the list, move through the list, find out if there are more elements, and find the current list item. It is easy to implement and has certain advantages. However, the Iterator of choice in Java is the following:

public interface Enumeration {
    public boolean hasMoreElements();
    public Object nextElement();
}

2 Examples

DvdListIterator.java - the Iterator Interface

public interface DvdListIterator {
    public void first();
    public void next();
    public boolean isDone();
    public String currentItem();                 
}

DvdList.java - the Concrete Aggregate (with a Concrete Iterator inner class)

public class DvdList {
	private String[] titles;
	//Yes, it would be easier to do this whole example with ArrayList
	// and ListIterator, but it certainly wouldn't be as much fun!
	private int titleCount;
	//titleCount is always a real count of titles,but one ahead of itself as a subscript
	private int arraySize;

	public DvdList() {
		titles = new String[3];
		//using 3 to demonstrate array expansion more easily
		// not for efficency
		titleCount = 0;
		arraySize = 3;
	}
	public int count() {
		return titleCount;
	}
	public void append(String titleIn) {
		if (titleCount >= arraySize) {
			String[] tempArray = new String[arraySize];
			for (int i = 0; i < arraySize; i++) {
				tempArray[i] = titles[i];
			}
			titles = null;
			arraySize = arraySize + 3;
			titles = new String[arraySize];
			for (int i = 0; i < arraySize - 3; i++) {
				titles[i] = tempArray[i];
			}
		}// if
		titles[titleCount++] = titleIn;
	}
	public void delete(String titleIn) {
		boolean found = false;
		for (int i = 0; i < titleCount - 1; i++) {
			if (! found) {
				if (titles[i].equals(titleIn)) {
					found = true;
					titles[i] = titles[i + 1];
				}
			} else {
				if (i < titleCount - 1) {
					titles[i] = titles[i + 1];
				} else {
					titles[i] = null;
				}
			}
		}// for
		if (found) {
			--titleCount;
		}
	}
	public DvdListIterator createIterator() {
		return new InnerIterator();
	}

	//note: 
	// This example shows the Concrete Iterator as an inner class.
	// The Iterator Pattern in GoF does allow for multiple types of 
	// iterators for a given list or "Aggregate".  This could be 
	// accomplished with multiple Iterators in multiple inner classes.
	// The createIterator class would then have multiple variations.
	// This, however, assumes that you will have a limited number of
	// iterator variants - which is normally the case.  If you do want
	// more flexibility in iterator creation, the iterators should not
	// be in inner classes, and perhaps some sort factory should be 
	// employed to create them.
	private class InnerIterator implements DvdListIterator {
		private int currentPosition = 0;
		private InnerIterator() {}
		public void first() {
			currentPosition = 0;
		}
		public void next() {
			if (currentPosition < titleCount) {
				currentPosition++;
			}
		}
		public boolean isDone() {
			if (currentPosition >= titleCount) {
				return true;
			} else {
				return false;
			}
		}
		public String currentItem() {
			return titles[currentPosition];
		}
	}
}

TestDvdIterator.java - testing the iterator

public class TestDvdIterator {
    public static void main(String[] args) {
        DvdList fiveShakespeareMovies = new DvdList();
        fiveShakespeareMovies.append("10 Things I Hate About You");
        fiveShakespeareMovies.append("Shakespeare In Love");
        fiveShakespeareMovies.append("O (2001)");
        fiveShakespeareMovies.append("American Pie 2");
        fiveShakespeareMovies.append("Scotland, PA.");
        fiveShakespeareMovies.append("Hamlet (2000)");

        DvdListIterator fiveShakespeareIterator = fiveShakespeareMovies.createIterator();
        while (! fiveShakespeareIterator.isDone()) {
            System.out.println(fiveShakespeareIterator.currentItem());
            fiveShakespeareIterator.next();
        }
        fiveShakespeareMovies.delete("American Pie 2");
        System.out.println();                                                                                 
        fiveShakespeareIterator.first();
        while (! fiveShakespeareIterator.isDone()) {
            System.out.println(fiveShakespeareIterator.currentItem());
            fiveShakespeareIterator.next();
        }

    }
}

Test Results



UML






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值