1.迭代器模式简介
迭代器模式:属于设计模式中的【行为模式】
简单介绍:迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
举例:分别访问List、Array、Map 、Set 等集合的方式是不同的,通过迭代器模式可以提供一种统一的方式实现顺序访问集合中的各个元素;
2.具体案例分析
假设有个快餐店请人做了一套系统;
早点供应系统-菜单用 List 数据结构存放数据;运行一段时间后效果非常好,
于是又请人升级系统添加了 晚餐供应模块-此时的菜单用的是 数组 存放的;
但是当服务员要从系统中打印菜单时-就发现很不方便;因为List、数组的遍历方式是不一样的;
这种情况我们的 迭代器模式 就有了用武之地;
【由于是不同的研发人员研发的对应菜单,所有这中情况非常常见】
下面我们具体来实现以下以上场景
我们先定义一个菜单对象
/**
* 具体的菜单类:包含菜品名称,菜品价格
*/
public class A1_Menu {
/**
* 菜品名称
*/
private String foodName;
/**
* 菜品价格
*/
private String foodPrice;
public A1_Menu(String foodName,String foodPrice){
this.foodName = foodName;
this.foodPrice = foodPrice;
}
public String getFoodName() {
return foodName;
}
public void setFoodName(String foodName) {
this.foodName = foodName;
}
public String getFoodPrice() {
return foodPrice;
}
public void setFoodPrice(String foodPrice) {
this.foodPrice = foodPrice;
}
}
定义早餐菜单
/**
* 早餐 菜单 菜品集合
*/
public class A2_Breakfask {
/**
* 菜单列表
*/
private List<A1_Menu> menuItems;
public A2_Breakfask(){
this.menuItems = new ArrayList<>();
// 默认就放入菜单项
addItem("可乐", "8元");
addItem("汉堡", "15元");
addItem("薯条", "13元");
addItem("鸡翅", "12元");
}
public void addItem(String name, String price) {
A1_Menu menu = new A1_Menu(name, price);
menuItems.add(menu);
}
/**
* 创建迭代器:重点 重点 重点
*/
public Iterator createIterator() {
return new A3_Breakfast_Iterator(menuItems);
}
}
定义早餐菜单的迭代器
/**
* 早餐迭代器
*/
public class A3_Breakfast_Iterator implements Iterator {
private List<A1_Menu> menuItems;//早餐 才当容器
private int position = 0;
public A3_Breakfast_Iterator(List<A1_Menu> menuItems){
this.menuItems = menuItems;
}
@Override
public boolean hasNext() {
if (position >= menuItems.size() || menuItems.get(position) == null) {
return false;
}
return true;
}
@Override
public Object next() {
A1_Menu menuItem = menuItems.get(position);
position++;
return menuItem;
}
}
定义晚餐菜单
/**
* 晚餐 菜单 菜品集合
*/
public class A3_Dinner {
private static final int MAX_ITEMS = 4;//菜单最大量
private int index = 0;
private A1_Menu[] menuItems;//存放所有菜品的容器
public A3_Dinner() {
menuItems = new A1_Menu[4];
// 默认就放入菜单项
addItem("浪漫套餐", "666元");
addItem("小龙虾套餐", "520元");
addItem("铁板鱿鱼", "66元");
addItem("炭烤扇贝", "88元");
}
public void addItem(String name, String price) {
A1_Menu menu = new A1_Menu(name, price);
if (index >= MAX_ITEMS) {
System.err.println("对不起, 菜单页满了");
} else {
menuItems[index] = menu;
index++;
}
}
/**
* 创建迭代器:重点 重点 重点
*/
public Iterator createIteraotr() {
return new A4_Dinner_Iterator(menuItems);
}
}
定义晚餐菜单的迭代器
/**
* 晚餐 菜单迭代器
*/
public class A4_Dinner_Iterator implements Iterator {
private A1_Menu[] menuItems;//早餐 菜品集合
private int position = 0;
public A4_Dinner_Iterator(A1_Menu[] menuItems){
this.menuItems = menuItems;
}
/**
* 判断菜单中是否还有下一个菜品
* @return
*/
@Override
public boolean hasNext() {
if (position >= menuItems.length || menuItems[position] == null) {
return false;
}
return true;
}
/**
* 取得 菜单中的下一个菜品
* @return
*/
@Override
public Object next() {
A1_Menu menuItem = menuItems[position];
position++;
return menuItem;
}
}
定义服务员打印菜单(客户端调用)
public class A6_Client {
public void print() {
System.out.println("================== 早餐菜单 ======================");
A2_Breakfask pancakeHouseShop = new A2_Breakfask();
Iterator pancakeHouseMenuIterator = pancakeHouseShop.createIterator();
printMenu(pancakeHouseMenuIterator);
System.out.println("=================== 晚餐菜单 =====================");
A3_Dinner dinnerShop = new A3_Dinner();
Iterator dinnerMenuIterator = dinnerShop.createIteraotr();
printMenu(dinnerMenuIterator);
}
private void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
A1_Menu menu = (A1_Menu) iterator.next();
System.out.println("名称: " + menu.getFoodName() + "======== 价格: " + menu.getFoodPrice());
}
}
public static void main(String[] args) {
A6_Client waiter = new A6_Client();
waiter.print();
}
}
打印信息
================== 早餐菜单 ======================
名称: 可乐======== 价格: 8元
名称: 汉堡======== 价格: 15元
名称: 薯条======== 价格: 13元
名称: 鸡翅======== 价格: 12元
=================== 晚餐菜单 =====================
名称: 浪漫套餐======== 价格: 666元
名称: 小龙虾套餐======== 价格: 520元
名称: 铁板鱿鱼======== 价格: 66元
名称: 炭烤扇贝======== 价格: 88元
3.优点
- 支持以不同方式遍历一个聚合对象
- 迭代器简化了聚合类
- 在同一个聚合上可以有多个遍历
- 增加新的聚合类和迭代器无需修改原有代码,满足“开闭原则”的要求
4.缺点
由于存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,增加了系统的复杂性