设计模式之迭代器模式浅析

迭代器提供一种方式遍历集合,而又无需暴露集合的实现
/**
 * 设计原则:
 *   单一原则:一个类应该只有一个引起变化的原因
 *   内聚--用来衡量一个类或者模块紧密的达到单一目的或责任
 *   高内聚--表示一个类或者模块只支持一个/一组相关功能
 * 
 * 迭代器模式:
 *   提供一种顺序访问聚合对象元素的方法,而又不暴露其内部元素
 * 迭代器将遍历聚合对象的任务封装到一个对象中。
 * 
 * 示例:
 *   咖啡厅菜单、煎饼屋早餐、中国菜午餐
 * 通过菜单接口 提供给客户统一的访问菜单项的方式 而不用知道菜单项的管理方式
 * 
 * 但是当我们想在菜单中嵌套菜单时 或者说有多层菜单嵌套时 就需要使用组合模式
 * @author Administrator
 *
 */


统一的接口 菜单类

package com.undergrowth.iterator;

import java.util.Iterator;

/**
 * 设计原则:
 *   单一原则:一个类应该只有一个引起变化的原因
 *   内聚--用来衡量一个类或者模块紧密的达到单一目的或责任
 *   高内聚--表示一个类或者模块只支持一个/一组相关功能
 * 
 * 迭代器模式:
 *   提供一种顺序访问聚合对象元素的方法,而又不暴露其内部元素
 * 迭代器将遍历聚合对象的任务封装到一个对象中。
 * 
 * 示例:
 *   咖啡厅菜单、煎饼屋早餐、中国菜午餐
 * 通过菜单接口 提供给客户统一的访问菜单项的方式 而不用知道菜单项的管理方式
 * 
 * 但是当我们想在菜单中嵌套菜单时 或者说有多层菜单嵌套时 就需要使用组合模式
 * @author Administrator
 *
 */
public interface Menu {
	/**
	 * 返回菜单项的迭代器
	 * @return
	 */
   public Iterator createIterator();
   
}

煎饼屋菜单

package com.undergrowth.iterator;


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

/**
 * 煎饼屋菜单  使用ArrayList存放菜单项
 * @author Administrator
 *
 */
public class PanCakeHouse implements Menu {

	List<MenuItem> items=new ArrayList<MenuItem>();
	
	public PanCakeHouse(){
		addMenuItem(new MenuItem("热干面", 10, "地道的武汉热干面", true));
		addMenuItem(new MenuItem("过桥米线", 8, "正宗的云南过桥米线", true));
		addMenuItem(new MenuItem("鸡蛋肠粉", 80, "广州的地道早餐", false));
	}
	
	private void addMenuItem(MenuItem menuItem) {
		// TODO Auto-generated method stub
		items.add(menuItem);
	}

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

}

中国菜菜单

package com.undergrowth.iterator;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 中餐 使用hashmap存储 菜单项
 * @author Administrator
 *
 */
public class ChineseFood implements Menu {

	Map<String, MenuItem> items=new HashMap<>();
	
	public ChineseFood(){
		addMenuItem(new MenuItem("宫保鸡", 45, "宫保鸡丁是川菜的代表菜,由鸡脯肉、干辣椒、花生米炒制而成,香辣好吃", false));
		addMenuItem(new MenuItem("糖醋里脊", 78, "糖醋里脊色泽红亮、酸甜可口、外酥里嫩", false));
		addMenuItem(new MenuItem("烤鸭", 80, "北京烤鸭,被誉为“天下美味”而驰名中外,它更以色泽红润,肉质细嫩,味道醇厚,肥而不腻的特色而享誉海内外", false));
	}
	
	
	private void addMenuItem(MenuItem menuItem) {
		// TODO Auto-generated method stub
		items.put(menuItem.getName(), menuItem);
	}


	@Override
	public Iterator createIterator() {
		// TODO Auto-generated method stub
		return items.values().iterator();
	}

}

咖啡厅菜单

package com.undergrowth.iterator;

import java.util.Iterator;

/**
 * 咖啡厅菜单 使用数组存储菜单项
 * @author Administrator
 *
 */
public class CoffeeMenu implements Menu {

	MenuItem[] items;
	int count=0;
	public CoffeeMenu(){
		items=new MenuItem[5];
		addMenuItem(new MenuItem("拿铁咖啡", 100, "咖啡与牛奶的交融", true));
		addMenuItem(new MenuItem("越南咖啡", 200, "采用纯正的越南咖啡豆", true));
		addMenuItem(new MenuItem("美式咖啡", 80, "清新的风味中不失本香", true));
		addMenuItem(new MenuItem("爱尔兰咖啡", 220, "融入砂糖、爱尔兰酒", true));
		addMenuItem(new MenuItem("皇家咖啡", 280, "流传于宫廷之中", true));
	}
	
	
	private void addMenuItem(MenuItem menuItem) {
		// TODO Auto-generated method stub
		items[count++]=menuItem;
	}


	@Override
	public Iterator createIterator() {
		// TODO Auto-generated method stub
		return new CoffeeIterator(items);
	}

}

咖啡厅菜单的迭代器

package com.undergrowth.iterator;

import java.util.Iterator;

/**
 * 将数组进行封装成迭代器
 * @author Administrator
 *
 */
public class CoffeeIterator implements Iterator {
	MenuItem[] items;
	int count;
	public CoffeeIterator(MenuItem[] items){
		this.items=items;
		count=0;
	}
	
	@Override
	public boolean hasNext() {
		// TODO Auto-generated method stub
		return count<items.length;
	}

	@Override
	public Object next() {
		// TODO Auto-generated method stub
		return items[count++];
	}

	@Override
	public void remove() {
		// TODO Auto-generated method stub
		throw new UnsupportedOperationException();
	}

}

菜单项

package com.undergrowth.iterator;

/**
 * 菜单项
 * @author Administrator
 *
 */
public class MenuItem {

	String name;
	float price;
	String description;
	boolean vegetarian;
	public MenuItem(String name, float price, String description,
			boolean vegetarian) {
		super();
		this.name = name;
		this.price = price;
		this.description = description;
		this.vegetarian = vegetarian;
	}
	@Override
	public String toString() {
		return "MenuItem [name=" + name + ", price=" + price + ", description="
				+ description + ", vegetarian=" + vegetarian + "]";
	}
	public String getName() {
		return name;
	}
	public float getPrice() {
		return price;
	}
	public String getDescription() {
		return description;
	}
	public boolean isVegetarian() {
		return vegetarian;
	}
	
	
}

服务员打印菜单

package com.undergrowth.iterator;

import java.util.Iterator;


/**
 * 服务员 用于打印菜单
 * @author Administrator
 *
 */
public class Waitress {
	
	Menu panMenu;
	Menu coffeeMenu;
	Menu chineseMenu;
	public Waitress(Menu panMenu, Menu coffeeMenu, Menu chineseMenu) {
		super();
		this.panMenu = panMenu;
		this.coffeeMenu = coffeeMenu;
		this.chineseMenu = chineseMenu;
	}
	
	public void printMenu(){
		System.out.println("==============开始打印菜单==============");
		System.out.println("   ===========开始打印咖啡菜单===========   ");
		Iterator<MenuItem> iteratorMenu=coffeeMenu.createIterator();
		printMenu(iteratorMenu);
		System.out.println("   ===========结束打印咖啡菜单===========   ");
		System.out.println("   ===========开始打印中国菜菜单===========   ");
		iteratorMenu=chineseMenu.createIterator();
		printMenu(iteratorMenu);
		System.out.println("   ===========结束打印中国菜菜单===========   ");
		System.out.println("   ===========开始打印煎饼屋菜单===========   ");
		iteratorMenu=panMenu.createIterator();
		printMenu(iteratorMenu);
		System.out.println("   ===========结束打印煎饼屋菜单===========   ");
		System.out.println("==============结束打印菜单==============");
	}

	private void printMenu(Iterator<MenuItem> iteratorMenu) {
		// TODO Auto-generated method stub
		for (Iterator iterator = iteratorMenu; iterator.hasNext();) {
			MenuItem miItem = (MenuItem) iterator.next();
			System.out.println(miItem);
		}
	}
	
	
}

为了更好的扩展 使用List存放菜单 上面类的变体

package com.undergrowth.iterator;

import java.util.Iterator;
import java.util.List;

import com.undergrowth.adapter.EnumeIteratorAdapter;


/**
 * 服务员 用于打印菜单 为了更易于扩展 使用List存放菜单
 * @author Administrator
 *
 */
public class WaitressList {
	
	List<Menu> menus;
	public WaitressList(List<Menu> menus) {
		super();
		this.menus = menus;
	}

	public void printMenu(){
		System.out.println("==============开始打印菜单==============");
		Iterator<Menu> menusIterator=menus.iterator();
		while(menusIterator.hasNext()){
			Menu menu=menusIterator.next();
			printMenu(menu.createIterator());
		}
		System.out.println("==============结束打印菜单==============");
	}

	private void printMenu(Iterator<MenuItem> iteratorMenu) {
		// TODO Auto-generated method stub
		System.out.println("   ===========开始打印新菜单===========   ");
		for (Iterator iterator = iteratorMenu; iterator.hasNext();) {
			MenuItem miItem = (MenuItem) iterator.next();
			System.out.println(miItem);
		}
		System.out.println("   ===========结束打印新菜单===========   ");
	}
	
	
}

测试

package com.undergrowth.iterator.test;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.undergrowth.iterator.ChineseFood;
import com.undergrowth.iterator.CoffeeMenu;
import com.undergrowth.iterator.Menu;
import com.undergrowth.iterator.PanCakeHouse;
import com.undergrowth.iterator.Waitress;
import com.undergrowth.iterator.WaitressList;

public class WaitressTest {

	@Test
	public void test() {

    Menu panMenu = new PanCakeHouse();
	Menu coffeeMenu = new CoffeeMenu();
	Menu chineseMenu = new ChineseFood();
	Waitress waitress=new Waitress(panMenu, coffeeMenu, chineseMenu);
    
	waitress.printMenu();
		
	System.out.println("\n\n\n\n");
	
	List<Menu> menus=new ArrayList<>();
	menus.add(panMenu);
	menus.add(coffeeMenu);
	menus.add(chineseMenu);
	WaitressList waitressList=new WaitressList(menus);
	waitressList.printMenu();
	
	}

}

结果输出

==============开始打印菜单==============
   ===========开始打印咖啡菜单===========   
MenuItem [name=拿铁咖啡, price=100.0, description=咖啡与牛奶的交融, vegetarian=true]
MenuItem [name=越南咖啡, price=200.0, description=采用纯正的越南咖啡豆, vegetarian=true]
MenuItem [name=美式咖啡, price=80.0, description=清新的风味中不失本香, vegetarian=true]
MenuItem [name=爱尔兰咖啡, price=220.0, description=融入砂糖、爱尔兰酒, vegetarian=true]
MenuItem [name=皇家咖啡, price=280.0, description=流传于宫廷之中, vegetarian=true]
   ===========结束打印咖啡菜单===========   
   ===========开始打印中国菜菜单===========   
MenuItem [name=宫保鸡, price=45.0, description=宫保鸡丁是川菜的代表菜,由鸡脯肉、干辣椒、花生米炒制而成,香辣好吃, vegetarian=false]
MenuItem [name=糖醋里脊, price=78.0, description=糖醋里脊色泽红亮、酸甜可口、外酥里嫩, vegetarian=false]
MenuItem [name=烤鸭, price=80.0, description=北京烤鸭,被誉为“天下美味”而驰名中外,它更以色泽红润,肉质细嫩,味道醇厚,肥而不腻的特色而享誉海内外, vegetarian=false]
   ===========结束打印中国菜菜单===========   
   ===========开始打印煎饼屋菜单===========   
MenuItem [name=热干面, price=10.0, description=地道的武汉热干面, vegetarian=true]
MenuItem [name=过桥米线, price=8.0, description=正宗的云南过桥米线, vegetarian=true]
MenuItem [name=鸡蛋肠粉, price=80.0, description=广州的地道早餐, vegetarian=false]
   ===========结束打印煎饼屋菜单===========   
==============结束打印菜单==============





==============开始打印菜单==============
   ===========开始打印新菜单===========   
MenuItem [name=热干面, price=10.0, description=地道的武汉热干面, vegetarian=true]
MenuItem [name=过桥米线, price=8.0, description=正宗的云南过桥米线, vegetarian=true]
MenuItem [name=鸡蛋肠粉, price=80.0, description=广州的地道早餐, vegetarian=false]
   ===========结束打印新菜单===========   
   ===========开始打印新菜单===========   
MenuItem [name=拿铁咖啡, price=100.0, description=咖啡与牛奶的交融, vegetarian=true]
MenuItem [name=越南咖啡, price=200.0, description=采用纯正的越南咖啡豆, vegetarian=true]
MenuItem [name=美式咖啡, price=80.0, description=清新的风味中不失本香, vegetarian=true]
MenuItem [name=爱尔兰咖啡, price=220.0, description=融入砂糖、爱尔兰酒, vegetarian=true]
MenuItem [name=皇家咖啡, price=280.0, description=流传于宫廷之中, vegetarian=true]
   ===========结束打印新菜单===========   
   ===========开始打印新菜单===========   
MenuItem [name=宫保鸡, price=45.0, description=宫保鸡丁是川菜的代表菜,由鸡脯肉、干辣椒、花生米炒制而成,香辣好吃, vegetarian=false]
MenuItem [name=糖醋里脊, price=78.0, description=糖醋里脊色泽红亮、酸甜可口、外酥里嫩, vegetarian=false]
MenuItem [name=烤鸭, price=80.0, description=北京烤鸭,被誉为“天下美味”而驰名中外,它更以色泽红润,肉质细嫩,味道醇厚,肥而不腻的特色而享誉海内外, vegetarian=false]
   ===========结束打印新菜单===========   
==============结束打印菜单==============




对比 可以发现 使用List的方式 更具有扩展性 


迭代器提供一种方式遍历集合,而又无需暴露集合的实现

posted on 2014-12-16 23:37  liangxinzhi  阅读(136)  评论(0编辑  收藏  举报