迭代器模式(Iterator Pattern)

时间:2023-03-08 17:49:34

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

酒吧提供beer和wine:

迭代器模式(Iterator Pattern)

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:

迭代器模式(Iterator Pattern)

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

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

迭代器模式(Iterator Pattern)

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类中可以看出,其对集合的操作为遍历,那么封装类需要提供方法以使我们可以遍历其封装的不同集合

迭代器模式(Iterator Pattern)

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 Pattern)

不想实现的方法就抛出默认异常,上面的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();