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

        迭代器模式

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

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

        下面是具体例子:

菜单项的类: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的类型安全。

       但是,迭代器模式还存在一个问题,假如想在菜单中添加子菜单,迭代器模式是不可以实现的,这要用到接下来要将的“组合模式”。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值