迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露器内部的表示。
类图
java代码
// 菜单项
public class MenuItem {
private String name;
private float price;
public MenuItem(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
@Override
public String toString() {
return "MenuItem{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
// 菜单接口
public interface Menu {
Iterator iterator();
}
// 煎饼店菜单
public class PancakeHouseMenu implements Menu {
private ArrayList<MenuItem> items;
public PancakeHouseMenu() {
items = new ArrayList<>();
addItem("K&B's Pancake", 2.99f);
addItem("Regular Pancake", 2.59f);
addItem("Blueberry Pancake", 3.49f);
}
public void addItem(String name, float price) {
items.add(new MenuItem(name, price));
}
@Override
public Iterator iterator() {
return new PancakeHouseIterator(items);
}
}
// 餐厅菜单
public class DinerMenu implements Menu {
private MenuItem[] items;
private int MAX_ITEMS = 3;
private int position = 0;
public DinerMenu() {
items = new MenuItem[MAX_ITEMS];
addItem("BLT", 2.99f);
addItem("Soup", 3.29f);
addItem("Hot dog", 3.05f);
}
public void addItem(String name, float price) {
if (position < MAX_ITEMS) {
items[position++] = new MenuItem(name, price);
} else {
throw new ArrayIndexOutOfBoundsException("menu is full");
}
}
@Override
public Iterator iterator() {
return new DinerIterator(items);
}
}
// 迭代器接口
public interface Iterator {
boolean hasNext();
MenuItem next();
}
// 煎饼店菜单迭代器
public class PancakeHouseIterator implements Iterator {
private ArrayList<MenuItem> items;
private int position = 0;
public PancakeHouseIterator(ArrayList<MenuItem> items) {
this.items = items;
}
@Override
public boolean hasNext() {
return position < items.size();
}
@Override
public MenuItem next() {
return items.get(position++);
}
}
// 餐厅菜单迭代器
public class DinerIterator implements Iterator {
private MenuItem[] items;
private int position = 0;
public DinerIterator(MenuItem[] items) {
this.items = items;
}
@Override
public boolean hasNext() {
return position < items.length && items[position] != null;
}
@Override
public MenuItem next() {
return items[position++];
}
}
// 服务员
public class Waitress {
private Menu pancakeHouseMenu;
private Menu dinerMenu;
public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}
public void printMenu() {
printMenu(pancakeHouseMenu.iterator());
printMenu(dinerMenu.iterator());
}
public void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
// 测试类
public class Test {
public static void main(String[] args) {
new Test().test();
}
private void test() {
Menu pancakeHouseMenu = new PancakeHouseMenu();
Menu dinerMenu = new DinerMenu();
Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
waitress.printMenu();
}
}
注:
- 菜单的实现已经被封装起来了。女招待员不知道菜单是如何存储菜单项集合的。
- 只要实现迭代器,我们只需要一个循环,就可以多态的处理任何项的集合。
- 女招待员现在只是用一个接口(迭代器)。
- 迭代器能让我们游走于聚合内的每一个元素,而又不暴露其内部表示。
- 把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
java自带迭代器
// 菜单项
public class MenuItem {
private String name;
private float price;
public MenuItem(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
@Override
public String toString() {
return "MenuItem{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
// 菜单接口
public interface Menu {
Iterator iterator();
}
// 煎饼店菜单
public class PancakeHouseMenu implements Menu {
private ArrayList<MenuItem> items;
public PancakeHouseMenu() {
items = new ArrayList<>();
addItem("K&B's Pancake", 2.99f);
addItem("Regular Pancake", 2.59f);
addItem("Blueberry Pancake", 3.49f);
}
public void addItem(String name, float price) {
items.add(new MenuItem(name, price));
}
@Override
public Iterator iterator() {
// 直接使用List的迭代器
return items.iterator();
}
}
// 餐厅菜单
public class DinerMenu implements Menu {
private MenuItem[] items;
private int MAX_ITEMS = 3;
private int position = 0;
public DinerMenu() {
items = new MenuItem[MAX_ITEMS];
addItem("BLT", 2.99f);
addItem("Soup", 3.29f);
addItem("Hot dog", 3.05f);
}
public void addItem(String name, float price) {
if (position < MAX_ITEMS) {
items[position++] = new MenuItem(name, price);
} else {
throw new ArrayIndexOutOfBoundsException("menu is full");
}
}
@Override
public Iterator iterator() {
// 将数组转化为list,获得其迭代器
return Arrays.asList(items).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() {
printMenu(pancakeHouseMenu.iterator());
printMenu(dinerMenu.iterator());
}
public void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
// 测试类
public class Test {
public static void main(String[] args) {
new Test().test();
}
private void test() {
Menu pancakeHouseMenu = new PancakeHouseMenu();
Menu dinerMenu = new DinerMenu();
Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
waitress.printMenu();
}
}
参考文章
1. Head First 设计模式