您的位置:首页 > 编程语言 > Java开发

JAVA设计模式——迭代器模式

2012-09-18 11:44 477 查看
迭代器模式

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

迭代器模式把在元素之间游走的责任交给了迭代器,而不是聚合对象。这不仅让聚合的接口和实现变得更简洁,也可以让聚合更专注在它所应该专注的事情上面(也就是管理对象集合),而不必去理会遍历的事情。

下面是具体例子:

菜单项的类:MenuItem.java

package com.designpattern.iterator;

public class MenuItem {
String name;
String description;
boolean vegetarian;
double price;

public MenuItem(String name,
String description,
boolean vegetarian,
double price){
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}

public String getName() {
return name;
}

public String getDescription() {
return description;
}

public boolean isVegetarian() {
return vegetarian;
}

public double getPrice() {
return price;
}

}


菜单的共同接口(用于返回迭代器):Menu.java

package com.designpattern.iterator;

import java.util.Iterator;

/**
* 菜单的共同接口
* */
public interface Menu {
public Iterator<?> createIterator();
}


建立两个菜单:PancakeHouseMenu.java & DinerMenu.java,都实现Menu接口

package com.designpattern.iterator;

import java.util.ArrayList;
import java.util.Iterator;

/**
* 用ArrayList来存储菜单项,有内嵌的返回迭代器方法,menuItems.iterator();
* createIterator()方法中可以直接返回迭代器,不用自己写迭代器;
* */
public class PancakeHouseMenu implements Menu{
ArrayList<MenuItem> menuItems;

public PancakeHouseMenu(){
menuItems = new ArrayList<MenuItem>();

addItem("K&B's 薄煎饼早餐", "薄煎饼、清蛋和吐司", true, 2.99);
addItem("薄煎饼早餐例餐", "薄煎饼带煎蛋,香肠", false, 2.99);
addItem("蓝莓薄煎饼", "新鲜蓝莓和蓝莓糖浆做成的薄煎饼", true, 3.49);
addItem("松饼", "松饼,可以选择蓝莓或草莓", true, 3.59);
}

public void addItem(String name, String description,
boolean vegetarian, double price){
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}

//	public ArrayList<MenuItem> getMenuItems(){
//		return menuItems;
//	}

@Override
public Iterator<MenuItem> createIterator() {
// TODO Auto-generated method stub
return menuItems.iterator();
}

}


package com.designpattern.iterator;

import java.util.Iterator;

/**
* 用数组来存储菜单项,没有内嵌的返回迭代器方法;
* 需要自己写迭代器:DinerMenuIterator.java,继承自Iterator类。
* */
public class DinerMenu implements Menu{
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
MenuItem[] menuItems;

public DinerMenu(){
menuItems = new MenuItem[MAX_ITEMS];

addItem("素食BLT", "(煎)培根、生菜&西红柿,用麦皮面包做", true, 2.99);
addItem("BLT", "培根、生菜&西红柿", false, 2.99);
addItem("例汤", "一碗例汤,配土豆沙拉", false, 3.29);
addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.05);
}

public void addItem(String name,String description,
boolean vegetarian, double price){
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if(numberOfItems >= MAX_ITEMS){
System.err.println("Sorry, menu is full! Can't add item to menu.");
}else{
menuItems[numberOfItems] = menuItem;
numberOfItems +=1;
}
}

//	public MenuItem[] getMenuItems(){
//		return menuItems;
//	}

@Override
public Iterator<Object> createIterator() {
// TODO Auto-generated method stub
return new DinerMenuIterator(menuItems);
}
}


DinerMenu.java中用到的返回迭代器的类:DinerMenuIterator.java

package com.designpattern.iterator;

import java.util.Iterator;

/**
* 由于数组没有内嵌的返回迭代器的方法,因此需要写自己的迭代器;
* */
public class DinerMenuIterator implements Iterator<Object>{
MenuItem[] list;
int position = 0;

public DinerMenuIterator(MenuItem[] list){
this.list = list;
}

@Override
public boolean hasNext() {
// TODO Auto-generated method stub
if(position >= list.length || list[position] == null){
return false;
}else{
return true;
}
}

@Override
public Object next() {
// TODO Auto-generated method stub
MenuItem menuItem = list[position];
position += 1;
return menuItem;
}

@Override
public void remove() {
// TODO Auto-generated method stub
if(position <= 0){
throw new IllegalStateException("You can't remove an item until you've done at least one next().");
}
if(list[position - 1] != null){
for(int i = position-1;i<(list.length -1);i++){
list[i] = list[i+1];
}
list[list.length-1] = null;
}
}

}


具体操作菜单的类:Waitress.java

package com.designpattern.iterator;

import java.util.Iterator;

/**
* 操作菜单的类
* */
public class Waitress {
Menu pancakeHouseMenu;
Menu dinerMenu;

public Waitress(Menu pancakeHouseMenu, Menu dinerMenu){
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}

public void printMenu(){
Iterator<?> pancakeIterator = pancakeHouseMenu.createIterator();
Iterator<?> dinerIterator = dinerMenu.createIterator();
System.out.println("MENU\n----\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH");
printMenu(dinerIterator);
}

private void printMenu(Iterator<?> iterator){
while(iterator.hasNext()){
MenuItem menuItem = (MenuItem) iterator.next();
System.out.println(menuItem.getName() + ",");
System.out.println(menuItem.getPrice() + "---");
System.out.println(menuItem.getDescription());
}
}
}


测试类:Test.java

package com.designpattern.iterator;

public class Test {
public static void main(String[] args) {
Menu pancakeHouseMenu = new PancakeHouseMenu();
Menu dinerMenu = new DinerMenu();

Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
waitress.printMenu();
}
}


小结:
两个菜单都实现了Menu接口,Waitress类可以直接利用接口引用每一个菜单对象。这样通过“针对接口编程,而不是针对实现编程”,我们就可以减少Waitress类与具体类之间的依赖。

此外,如果想要再添加新的菜单也会变得很容易,只需要按照前面两个菜单类写一个继承Menu接口的菜单类,再在Waitress类中添加菜单类的对象即可。即Waitress类具有更好的扩展性。

JAVA 5包含了一种新形式的for语句,称for/in。这可以让你在一个集合或者一个数组中遍历,而且不需要显式创建迭代器。但需要使用JAVA 5的泛型新特性来确保for/in的类型安全。

但是,迭代器模式还存在一个问题,假如想在菜单中添加子菜单,迭代器模式是不可以实现的,这要用到接下来要将的“组合模式”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: