我们接着上次迭代器模式的例子,来优化一下,这次我们使用java自带的迭代器
因为 PancakeHouseMenu这个类里面的集合是ArrayList类型,则可以直接使用java默认的迭代器,不需要写它的迭代器
DinerMenu里面的集合类型是数组,而java默认的迭代器不支持数组的迭代,则需要自定义迭代器
我们再来重新整理一下各个类
首先是菜单项类,它没有任何变化
package iterator.demo;
/**
* 菜单项
*/
public class MenuItem
{
private String name; //菜单项名称
private String description; //描述
private double price; //价格
public MenuItem(String name,
String description,
double price)
{
this.name = name;
this.description = description;
this.price = price;
}
public String toString()
{
return (name + ": "+description+", $" + price);
}
}
接着是菜单类
package iterator.demo;
import java.util.Iterator;
public interface Menu
{
/**
* 添加菜单项
* @param name
* @param description
* @param price
*/
void addItem(String name, String description, double price);
/**
* 获取菜单项集合
*/
Object getMenuItems();
/**
* 获取迭代器
* @return
*/
Iterator<MenuItem> createIterator();
}
然后是两个餐厅,他们都实现了Menu接口,煎饼屋餐厅使用的集合类支持迭代器,而对乡村餐厅使用的数组,不支持java自带的迭代器,需要自定义一个迭代器来遍历数组
package iterator.demo;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 煎饼屋餐厅
*/
public class PancakeHouseMenu implements Menu
{
private ArrayList<MenuItem> menuItems;
public PancakeHouseMenu()
{
menuItems = new ArrayList();
addItem("薄煎饼早餐",
"薄煎饼、鸡蛋和土司",
2.99);
addItem("蓝莓薄煎饼",
"新鲜蓝莓和蓝莓果酱做成的薄煎饼",
2.99);
addItem("松饼",
"松饼,可以选择蓝莓或者草莓口味",
3.59);
}
public void addItem(String name, String description, double price)
{
MenuItem menuItem = new MenuItem(name, description, price);
menuItems.add(menuItem);
}
public ArrayList<MenuItem> getMenuItems()
{
return menuItems;
}
public Iterator createIterator() {
return menuItems.iterator();
}
}
package iterator.demo;
import java.util.Iterator;
/**
* 对象村餐厅
*/
public class DinerMenu implements Menu
{
private static final int MAX_ITEMS = 4;
private int numberOfItems = 0;
private MenuItem[] menuItems;
public DinerMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("素食 BLT", "(煎)培根, 生菜和西红柿", 2.99);
addItem("清汤", "一碗清汤, 配土豆沙拉", 3.29);
addItem("热狗", "一个热狗, 酸菜, 芝士, 洋葱", 3.05);
addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", 3.99);
}
public void addItem(String name, String description, double price)
{
MenuItem menuItem = new MenuItem(name, description, price);
if (numberOfItems >= MAX_ITEMS)
{
System.err.println("抱歉, 菜单已满! 不能添加菜单项");
}
else
{
menuItems[numberOfItems] = menuItem;
numberOfItems = numberOfItems + 1;
}
}
public MenuItem[] getMenuItems()
{
return menuItems;
}
public Iterator createIterator() {
return new DinerMenuIterator(menuItems);
}
}
由于对乡村餐厅DinerMenu里面是数组类型的集合,则需要自定义一个迭代器并实现Iterator接口
package iterator;
import item.MenuItem;
import java.util.Iterator;
public class DinerMenuIterator implements Iterator
{
private MenuItem[] menuItems;
private int position = 0;
public DinerMenuIterator(MenuItem[] menuItems)
{
this.menuItems = menuItems;
}
@Override
public boolean hasNext()
{
if (position >= menuItems.length || menuItems[position] == null)
return false;
else
return true;
}
@Override
public MenuItem next()
{
MenuItem menuItem = menuItems[position++];
return menuItem;
}
}
接着来看看女服务员,我们把具体的类型改成了接口类型,这样 “通过针对接口编程,而不是针对实现编程“,我们就可以减少女接待员和具体类之间的依赖
package iterator.demo;
import java.util.Iterator;
public class Waitress
{
private Menu pancakeHouseMenu;
private 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();
printMenu(pancakeIterator);
printMenu(dinerIterator);
}
private void printMenu(Iterator<MenuItem> iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = iterator.next();
System.out.println(menuItem);
}
}
}
最后测试类,女服务员根据传入的餐厅报菜单,也能完成之前的功能
package iterator.demo;
public class Client
{
public static void main(String[] args)
{
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
DinerMenu dinerMenu = new DinerMenu();
Waitress waitress=new Waitress(pancakeHouseMenu,dinerMenu);
waitress.printMenu();
}
}
其实女服务员仍有改进的地方,每次如果新加入一个餐厅,都要修改女服务员里面的内容,这不符合开闭原则
重新优化一下 ,将多个餐厅变成一个餐厅集合,这样每次增加一个餐厅类,就不需要修改女服务员了
package iterator.demo;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 服务员类,根据餐厅打印菜单
*/
public class Waitress
{
ArrayList<Menu> menus;
public Waitress(ArrayList<Menu> menus)
{
this.menus = menus;
}
public void printMenu() {
Iterator<Menu> menusIterator = menus.iterator();
while (menusIterator.hasNext())
{
Menu menu = menusIterator.next();
printMenu(menu.createIterator());
}
}
private void printMenu(Iterator<MenuItem> iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = iterator.next();
System.out.println(menuItem);
}
}
}
测试类要麻烦一点,不过不用修改女服务员,实现了开闭原则
package iterator.demo;
import java.util.ArrayList;
public class Client
{
public static void main(String[] args)
{
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
DinerMenu dinerMenu = new DinerMenu();
ArrayList list = new ArrayList();
list.add(pancakeHouseMenu);
list.add(dinerMenu);
Waitress waitress=new Waitress(list);
waitress.printMenu();
}
}