迭代器模式(Iterator Pattern)

迭代器模式定义:Iterator Pattern提供一种方法顺序访问一个聚合元素中的各个元素,而又不暴漏内部方法

酒吧提供beer和wine:


public class Bar {
	private List<String> barMenu;
	
	public Bar(){
		barMenu = new ArrayList<String>();
		barMenu.add("beer");
		barMenu.add("wine");
	}
	
	public List<String> getMenu(){
		return barMenu;
	}
}

餐厅提供rice、soup和noodles:


public class Restaurant {
	private String[] restaurantMenu;
	
	public Restaurant(){
		restaurantMenu = new String[3];
		restaurantMenu[0] = "rice";
		restaurantMenu[1] = "soup";
		restaurantMenu[2] = "noodles";
	}
	
	public String[] getMenu(){
		return restaurantMenu;
	}
}

现在要将酒吧与餐厅整合为一个点餐系统,在该点餐系统中既能看到酒吧的所有饮品,又能看到餐厅的所有餐点,通常的处理方式为:


public class OrderSystem {
	private Bar bar;
	private Restaurant reataurant;
	
	public OrderSystem(Bar bar,Restaurant reataurant){
		this.bar = bar;
		this.reataurant = reataurant;
	}
	
	public void printMenu(){
		List<String> bMenus = bar.getMenu();
		String[] rMenus = reataurant.getMenu();
		if(null != bMenus && bMenus.size() > 0){
			for(String name : bMenus){
				System.out.println(name);
			}
		}
		if(null != rMenus){
			for(int i = 0;i < rMenus.length; i++){
				if(null != rMenus[i]){
					System.out.println(rMenus[i]);
				
			}
		}
	}
}

1,OrderSystem类与具体集合类型(String[]以及List<String>)、具体实现(for循环)耦合

2,OrderSystem类与具体餐厅类耦合,即使这两个餐厅类提供的方法相同

先来考虑问题1,显然我们需要进行封装以隐藏具体集合类型与实现过程

从OrderSystem类中可以看出,其对集合的操作为遍历,那么封装类需要提供方法以使我们可以遍历其封装的不同集合


public interface Iterator {
	public boolean hasNext();
	
	public Object next() throws Exception;
}
public class BarIterator implements Iterator {
	private List<String> menu;
	int nextPosition = 0;
	
	public BarIterator(List<String> menu){
		this.menu = menu;
	}
	
	public boolean hasNext() {
		if(menu.size() > nextPosition && null != menu.get(nextPosition)){
			return true;
		}
		return false;
	}

	public Object next() throws Exception {
		if(menu.size() > nextPosition && null != menu.get(nextPosition)){
			Object result = menu.get(nextPosition);
			nextPosition++;
			return result;
		}
		throw new Exception("越界");
	}
}
public class RestaurantIterator implements Iterator {
	private String[] menu;
	int nextPosition = 0;
	
	public RestaurantIterator(String[] menu){
		this.menu = menu;
	}
	
	public boolean hasNext() {
		if(menu.length > nextPosition && null != menu[nextPosition]){
			return true;
		}
		return false;
	}

	public Object next() throws Exception {
		if(menu.length > nextPosition && null != menu[nextPosition]){
			Object result = menu[nextPosition];
			nextPosition++;
			return result;
		}
		throw new Exception("越界");
	}
}
public class Bar {
	private List<String> barMenu;
	
	public Bar(){
		barMenu = new ArrayList<String>();
		barMenu.add("beer");
		barMenu.add("wine");
	}
	
	public Iterator getMenu(){
		return new BarIterator(barMenu);
	}
}
public class Restaurant {
	private String[] restaurantMenu;
	
	public Restaurant(){
		restaurantMenu = new String[3];
		restaurantMenu[0] = "rice";
		restaurantMenu[1] = "soup";
		restaurantMenu[2] = "noodles";
	}
	
	public RestaurantIterator getMenu(){
		return new RestaurantIterator(restaurantMenu);
	}
}
public class OrderSystem {
	private Bar b;
	private Restaurant r;
	
	public OrderSystem(Bar b,Restaurant r){
		this.b = b;
		this.r = r;
	}
	
	public void printMenu(){
		Iterator bit = b.getMenu();
		Iterator rit = r.getMenu();
		printMenu(bit);
		printMenu(rit);
	}
	
	private void printMenu(Iterator it){
		try{
			while(it.hasNext()){
				Object tmp = it.next();
				if(null != tmp){
					System.out.println(tmp.toString());
				}
			}
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
	}
	
	public static void main(String[] args){
		Bar b = new Bar();
		Restaurant r = new Restaurant();
		OrderSystem h = new OrderSystem(b,r);
		h.printMenu();
	}
}

封装的遍历方法没有加锁,在多线程环境下是不适用的

看看设计中的Iterator类是不是和java.util.Iterator十分相似?

/*
 * @(#)Iterator.java	1.27 06/07/24
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.util;

/**
 * An iterator over a collection.  Iterator takes the place of Enumeration in
 * the Java collections framework.  Iterators differ from enumerations in two
 * ways: <ul>
 *	<li> Iterators allow the caller to remove elements from the
 *	     underlying collection during the iteration with well-defined
 * 	     semantics.
 *	<li> Method names have been improved.
 * </ul><p>
 *
 * This interface is a member of the 
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @author  Josh Bloch
 * @version 1.27, 07/24/06
 * @see Collection
 * @see ListIterator
 * @see Enumeration
 * @since 1.2
 */
public interface Iterator<E> {
    /**
     * Returns <tt>true</tt> if the iteration has more elements. (In other
     * words, returns <tt>true</tt> if <tt>next</tt> would return an element
     * rather than throwing an exception.)
     *
     * @return <tt>true</tt> if the iterator has more elements.
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration.
     * @exception NoSuchElementException iteration has no more elements.
     */
    E next();

    /**
     * 
     * Removes from the underlying collection the last element returned by the
     * iterator (optional operation).  This method can be called only once per
     * call to <tt>next</tt>.  The behavior of an iterator is unspecified if
     * the underlying collection is modified while the iteration is in
     * progress in any way other than by calling this method.
     *
     * @exception UnsupportedOperationException if the <tt>remove</tt>
     *		  operation is not supported by this Iterator.
     
     * @exception IllegalStateException if the <tt>next</tt> method has not
     *		  yet been called, or the <tt>remove</tt> method has already
     *		  been called after the last call to the <tt>next</tt>
     *		  method.
     */
    void remove();
}
再来考虑问题2:与具体餐厅类耦合很容易处理-面向接口编程

这里使用java.util.Iterator


不想实现的方法就抛出默认异常,上面的Iterator类源代码中说的很清楚了:

public class RestaurantIterator implements Iterator<String> {
	private String[] menu;
	int nextPosition = 0;
	
	public RestaurantIterator(String[] menu){
		this.menu = menu;
	}
	
	public boolean hasNext() {
		if(menu.length > nextPosition && null != menu[nextPosition]){
			return true;
		}
		return false;
	}

	public String next(){
		if(menu.length > nextPosition && null != menu[nextPosition]){
			String result = menu[nextPosition];
			nextPosition++;
			return result;
		}
		throw new NoSuchElementException();
	}
	
	public void remove(){
		throw new UnsupportedOperationException();
	}
}
public interface R {
	public Iterator<String> getMenu();
}
public class Bar implements R{
	private List<String> barMenu;
	
	public Bar(){
		barMenu = new ArrayList<String>();
		barMenu.add("beer");
		barMenu.add("wine");
	}
	
	public Iterator<String> getMenu(){
		return barMenu.iterator();
	}
}
public class Restaurant implements R{
	private String[] restaurantMenu;
	
	public Restaurant(){
		restaurantMenu = new String[3];
		restaurantMenu[0] = "rice";
		restaurantMenu[1] = "soup";
		restaurantMenu[2] = "noodles";
	}
	
	public Iterator<String> getMenu(){
		return new RestaurantIterator(restaurantMenu);
	}
}
public class OrderSystem {
	private Bar b;
	private Restaurant r;
	
	public OrderSystem(Bar b,Restaurant r){
		this.b = b;
		this.r = r;
	}
	
	public void printMenu(){
		Iterator<String> bit = b.getMenu();
		Iterator<String> rit = r.getMenu();
		printMenu(bit);
		printMenu(rit);
	}
	
	private void printMenu(Iterator<String> it){
		try{
			while(it.hasNext()){
				Object tmp = it.next();
				if(null != tmp){
					System.out.println(tmp.toString());
				}
			}
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
	}
	
	public static void main(String[] args){
		Bar b = new Bar();
		Restaurant r = new Restaurant();
		OrderSystem h = new OrderSystem(b,r);
		h.printMenu();
	}
}
List可以自动返回一个封装好的Iterator
    /**
     * Returns an iterator over the elements in this list in proper sequence.
     *
     * @return an iterator over the elements in this list in proper sequence
     */
    Iterator<E> iterator();

posted @ 2013-07-16 11:08  心意合一  阅读(198)  评论(0编辑  收藏  举报