迭代器就是用来遍历集合的, 有时候需要遍历多个对象中的集合, 但是每个对象中的集合可能不一样,也许是List,也许是Array,也许是其他。 如果把每个对象中的集合都暴露给调用者,耦合性很大,而且也不安全。
比如,一家早餐店的菜单是包子,稀饭,豆浆… 一家午餐店的菜单是炒饭,面条…
对于两家店(两个不同的对象)来说,他们各自的设计是List<MenuItem> 和 MenuItem[] ; 各自有自己遍历菜单的方式。 现在两家合并了,服务员报菜单的时候,难道要分别调用两个对象的遍历方式? 如果不只两个对象呢?
这时候使用迭代器模式,每个对象创建自己的迭代器,遍历自己的集合。 服务员只需根据对象获取到对应的迭代器,调用迭代器的next()方法(不用关心底层方法是什么)。
角色:
抽象迭代器:可以自己定义,也可以使用java已有的。
具体迭代器:不同对象创建自己的迭代器,用于遍历自己的集合。
过程:
菜单:
public 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;
}
}
抽象饭店:
/**
* 饭店
*/
public abstract class Shop {
/**
* 创建迭代器,将店铺的菜单放到迭代器
* @return
*/
public abstract Iterator<MenuItem> createIterator();
}
早餐店:
public class BreakFastShop extends Shop{
private List<MenuItem> list;
public BreakFastShop() {
this.list = new ArrayList<>();
addMenuItem(new MenuItem("包子",2.5));
addMenuItem(new MenuItem("豆浆",2.5));
addMenuItem(new MenuItem("稀饭",2.0));
addMenuItem(new MenuItem("油条",2.0));
}
//添加菜单
public void addMenuItem(MenuItem item){
list.add(item);
}
@Override
public Iterator<MenuItem> createIterator() {
return new BreakFastIterator(list);
}
}
正餐店:
public class DinnerShop extends Shop {
private MenuItem[] items;
private int position;
public DinnerShop() {
this.items = new MenuItem[3];
this.position = 0;
addMenuItem(new MenuItem("炒饭", 13));
addMenuItem(new MenuItem("面条", 12));
addMenuItem(new MenuItem("水饺", 15));
}
//添加菜单
public void addMenuItem(MenuItem item) {
if (position == items.length) {
throw new IllegalArgumentException("菜单已满");
}
items[position] = item;
position++;
}
@Override
public Iterator<MenuItem> createIterator() {
return new DinnerIterator(items);
}
}
我们看到,不同的店铺都提供了,创建自己的迭代器的方法,用于遍历自己的菜单。
早餐店的迭代器:遍历List集合
public class BreakFastIterator implements Iterator {
private List<MenuItem> list;
private int position;
public BreakFastIterator(List<MenuItem> list) {
this.list = list;
position = 0;
}
@Override
public boolean hasNext() {
return position < list.size();
}
@Override
public Object next() {
MenuItem menuItem = list.get(position);
position++;
return menuItem;
}
}
正餐店的迭代器:遍历数组
public class DinnerIterator implements Iterator {
private MenuItem[] items;
private int position;
public DinnerIterator(MenuItem[] items) {
this.items = items;
this.position = 0;
}
@Override
public boolean hasNext() {
return position < items.length;
}
@Override
public Object next() {
MenuItem item = items[position];
position++;
return item;
}
}
服务员:现在两家店合并,服务员要报所有的菜单,不需要知道每家店底层的实现方式:
public class Waiter {
private List<Shop> shops;
public Waiter() {
this.shops = new ArrayList<>();
}
public void addShop(Shop shop){
shops.add(shop);
}
/**
* 打印所有店铺的菜单
*/
public void printMenuItems(){
if(shops != null){
for (Shop shop : shops) {
Iterator<MenuItem> iterator = shop.createIterator();
while (iterator.hasNext()){
MenuItem item = iterator.next();
System.out.println(item.getName() + ":" + item.getPrice() + "元");
}
}
}
}
}
测试:
public static void main(String[] args) {
BreakFastShop breakFastShop = new BreakFastShop();
DinnerShop dinnerShop = new DinnerShop();
Waiter waiter = new Waiter();
waiter.addShop(breakFastShop);
waiter.addShop(dinnerShop);
waiter.printMenuItems();
}