迭代器模式是什么?
迭代器模式提供一种方法顺序访问一个集合对象中的各个元素,而又不暴露其内部的表示。
迭代器模式解决什么问题?
现有MenuItem作为菜单项,BreakfastMenu采用ArrayList实现,LunchMenu采用数组实现:
class MenuItem {
private String name;
private Double price;
public MenuItem(String name, Double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public Double getPrice() {
return price;
}
}
class BreakfastMenu {
ArrayList<MenuItem> menuItems;
public BreakfastMenu() {
menuItems = new ArrayList<>();
addItem("包子", 1.5);
addItem("烧卖", 1.5);
}
public void addItem(String name, double price) {
MenuItem item = new MenuItem(name, price);
menuItems.add(item);
}
public ArrayList<MenuItem> getMenuItems() {
return menuItems;
}
}
class LunchMenu {
static final int MAX_ITEM = 6;
int number = 0;
MenuItem[] menuItems;
public LunchMenu() {
menuItems = new MenuItem[MAX_ITEM];
addItem("鱼香肉丝", 15);
addItem("西红柿炒蛋", 15);
}
public void addItem(String name, double price) {
MenuItem item = new MenuItem(name, price);
if (number > MAX_ITEM) {
System.out.println("菜单满了");
} else {
menuItems[number] = item;
number += 1;
}
}
public MenuItem[] getMenuItems() {
return menuItems;
}
}
如果要打印早午餐的菜单,只能通过getMenuItems()获取到ArrayList数据和数组数据分别进行打印
BreakfastMenu breakfastMenu = new BreakfastMenu();
ArrayList<MenuItem> breakfastMenuItems = breakfastMenu.getMenuItems();
for (int i = 0; i < breakfastMenuItems.size(); i++) {
System.out.println(breakfastMenuItems.get(i).getName() + breakfastMenuItems.get(i).getPrice());
}
LunchMenu lunchMenu = new LunchMenu();
MenuItem[] lunchMenuItems = lunchMenu.getMenuItems();
for (int i = 0; i < lunchMenuItems.length; i++) {
System.out.println(lunchMenuItems[i].getName() + lunchMenuItems[i].getPrice());
}
现如今两个菜单合并,以后可能有更多不同数据结构存储的菜单,如何将这些菜单统一遍历?
迭代器模式实现
迭代器接口
新建迭代器接口:
interface MyIterator {
boolean hasNext();
Object next();
}
迭代器实例
LunchMenuIterator处理数组的遍历,BreakfastMenuIterator处理ArrayList的遍历:
class LunchMenuIterator implements MyIterator {
MenuItem[] menuItems;
int position = 0;
public LunchMenuIterator(MenuItem[] menuItems) {
this.menuItems = menuItems;
}
@Override
public boolean hasNext() {
if (position >= menuItems.length || menuItems[position] == null) {
return false;
} else {
return true;
}
}
@Override
public Object next() {
MenuItem menuItem = menuItems[position];
position += 1;
return menuItem;
}
}
class BreakfastMenuIterator implements MyIterator {
ArrayList<MenuItem> menuItems;
int position = 0;
public BreakfastMenuIterator(ArrayList<MenuItem> menuItems) {
this.menuItems = menuItems;
}
@Override
public boolean hasNext() {
if (position >= menuItems.size() || menuItems.get(position) == null) {
return false;
} else {
return true;
}
}
@Override
public Object next() {
MenuItem menuItem = menuItems.get(position);
position += 1;
return menuItem;
}
}
用于创建迭代器的接口
新建Menu接口用于创建迭代器:
interface Menu {
MyIterator createIterator();
}
用于创建迭代器的实例
将LunchMenu和BreakfastMenu的getMenuItems()方法改为返回其对应迭代器:
class LunchMenu implements Menu {
static final int MAX_ITEM = 6;
int number = 0;
MenuItem[] menuItems;
public LunchMenu() {
menuItems = new MenuItem[MAX_ITEM];
addItem("鱼香肉丝", 15);
addItem("西红柿炒蛋", 15);
}
public void addItem(String name, double price) {
MenuItem item = new MenuItem(name, price);
if (number > MAX_ITEM) {
System.out.println("菜单满了");
} else {
menuItems[number] = item;
number += 1;
}
}
public MyIterator createIterator() {
return new LunchMenuIterator(menuItems);
}
}
class BreakfastMenu implements Menu {
ArrayList<MenuItem> menuItems;
public BreakfastMenu() {
menuItems = new ArrayList<>();
addItem("包子", 1.5);
addItem("烧卖", 1.5);
}
public void addItem(String name, double price) {
MenuItem item = new MenuItem(name, price);
menuItems.add(item);
}
public MyIterator createIterator() {
return new BreakfastMenuIterator(menuItems);
}
}
迭代过程
通过获取MyIterator,调用其中的hasNext()和next()即可对ArrayList和数组无差别遍历,还可对while循环进一步封装:
Menu breakfastMenu = new BreakfastMenu();
MyIterator breakfastIterator = breakfastMenu.createIterator();
while (breakfastIterator.hasNext()) {
MenuItem menuItem = (MenuItem) breakfastIterator.next();
System.out.println(menuItem.getName() + " " + menuItem.getPrice());
}
Menu lunchMenu = new LunchMenu();
MyIterator lunchIterator = lunchMenu.createIterator();
while (lunchIterator.hasNext()) {
MenuItem menuItem = (MenuItem) lunchIterator.next();
System.out.println(menuItem.getName() + " " + menuItem.getPrice());
}