1、迭代器模式概要
定义: 提供一种方法顺序的访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
比如在同时整合多个对象的代码时,每个对象所用的数据结构不同,如果想要让他们统一展现出来,就可以使用迭代器模式
迭代器是从前向后投遍历的,迭代器不用关心是使用什么样的数据结构
2、迭代器模式举例
对象村的早饭店和午饭店铺合并了,现在需要合并他们的菜单,但是早餐店的菜单是使用ArrayList,午餐店使用的是数组形式,我们如何把他们统一的展现出来呢?
我们先看看早餐店是怎么实现的
public class BreakFast {
ArrayList<Menu> menus;
public BreakFast() {
menus = new ArrayList<>();
addMenu("油条","传统北方早餐",true,2.0);
addMenu("八宝粥","多种粮食搭配",true,2.0);
addMenu("鸡蛋饼","传统早餐",true,5.0);
}
public void addMenu(String name,String description,boolean vegetarian,double price){
Menu menu = new Menu(name, description, vegetarian, price);
menus.add(menu);
}
public ArrayList getMenu(){
return menus;
}
}
我们再看看午餐店是怎么实现的
public class Lunch {
Menu[] menus;
int numIndex = 0;
public Lunch(Menu[] menus) {
menus = new Menu[6];
addMenu("宫保鸡丁","鸡肉和辣椒加上花生米",false,25.0);
addMenu("红烧肉","猪肉红烧",false,34);
addMenu("小青菜","素炒小青菜",true,12);
addMenu("西红柿炒鸡蛋","红配黄",true,20);
}
public void addMenu(String name,String description,boolean vegetarian,double price){
Menu menu = new Menu(name, description, vegetarian, price);
menus[numIndex] = menu;
numIndex++;
}
public Menu[] getMenus(){
return menus;
}
}
两个类中的getMenus都返回了他们各自的数据类型,但这不是我们想要的,因为我们无法用统一的代码处理他们(当然foreach是可以的,但是我们这里主要需要了解的是迭代器模式)
比如我们要处理他们就只能
public static void main(String[] args) {
BreakFast breakFast = new BreakFast();
Lunch lunch = new Lunch();
ArrayList<Menu> breakFasts = breakFast.getMenu();
Menu[] lunchs = lunch.getMenus();
System.out.println("-----------------这里是早餐----------------------");
for (int i = 0; i < breakFasts.size(); i++) {
Menu menu = breakFasts.get(i);
System.out.println(menu.getName() + " ");
System.out.println(menu.getDescription() + " ");
System.out.println(menu.getPrice() + " ");
}
System.out.println("-----------------这里是午餐----------------------");
for (int i = 0; i < lunchs.length; i++) {
Menu menu = lunchs[i];
System.out.println(menu.getName() + " ");
System.out.println(menu.getDescription() + " ");
System.out.println(menu.getPrice() + " ");
}
}
通过for循环来处理,如果多了一个晚餐的话,就需要再增加一点代码,再使用一遍for循环
为了解决这个问题,我们引入迭代器模式,我们通过一个迭代器,来使数据具有相同的返回结构
迭代器接口
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
}
上面是java所提供的迭代器实现的接口,在这里就不过多介绍,相信学习过集合框架的同学都知道迭代器的作用
我们只需要实现迭代器接口即可把上面的代码变形为同一而且可以复用的代码
public class BreakFast implements Iterable {
ArrayList<Menu> menus;
public BreakFast() {
menus = new ArrayList<>();
addMenu("油条","传统北方早餐",true,2.0);
addMenu("八宝粥","多种粮食搭配",true,2.0);
addMenu("鸡蛋饼","传统早餐",true,5.0);
}
public void addMenu(String name,String description,boolean vegetarian,double price){
Menu menu = new Menu(name, description, vegetarian, price);
menus.add(menu);
}
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
@Override
public Iterator iterator() {
return menus.iterator();
}
}
这样,在调用iterator方法后,我们就能很轻易的获取的迭代器模式的菜单
在测试代码中,我们只需要做一些微小的变动
public static void main(String[] args) {
BreakFast breakFast = new BreakFast();
Lunch lunch = new Lunch();
Iterator iterator = breakFast.iterator();
Menu[] lunchs = lunch.getMenus();
System.out.println("-----------------这里是早餐----------------------");
while (iterator.hasNext()){
Menu menu = (Menu) iterator.next();
System.out.println(menu.getName() + " ");
System.out.println(menu.getDescription() + " ");
System.out.println(menu.getPrice() + " ");
}
System.out.println("-----------------这里是午餐----------------------");
for (int i = 0; i < lunchs.length; i++) {
Menu menu = lunchs[i];
System.out.println(menu.getName() + " ");
System.out.println(menu.getDescription() + " ");
System.out.println(menu.getPrice() + " ");
}
}
在这里,我们只需要调用迭代器的方法,我们不再需要知道它的数据结构是什么了,这样我们就既可以隐藏数据类型,又可以遍历全部的元素