设计模式之迭代器模式以及单一职责原则
我们在使用集合的时候,往往需要用到遍历,这时候需要使用迭代器,但是不同集合的遍历方法不一样,所以迭代器的实现方法也不一样,但是为了面向抽象编程,客户端应该只知道如何使用迭代器进行遍历,而不需要知道迭代器是怎么实现的。这里就用到了迭代器模式。
所以说迭代器模式,就是对于不同集合,使用相同的迭代器接口,但采用不同的实现,也就是封装遍历。
比如说,客户端要实现对集合的遍历,这时候如果面向实现编程,就要知道有多少个集合,要怎么样遍历集合。但是如果采用了迭代器,客户端则只需要知道迭代器有哪些方法,是怎么使用的即可。
比如这时候我们需要遍历一个数组和一个ArrayList,ArrayList本来就是实现了Iterator接口,所以我们使用现成的,但是数组则不是,所以我们要自己编写一个类,实现Iterator接口,类图如下:
ArrayIterator类
import java.util.Iterator; /** 用来对数组进行迭代的迭代器 **/ public class ArrayIterator implements Iterator { MenuItem[] items; int position; public ArrayIterator(MenuItem[] items) { this.items=items; position=0; } public boolean hasNext() { if(items!=null) { if(position<items.length-1) { return true; } else return false; } return false; } public Object next() { return items[position++]; } public void remove() { throw new UnsupportedOperationException(); } }
DinerMenu类
/** 使用数组来保存 **/ import java.util.Iterator; public class DinerMenu implements Menu { MenuItem[] items; public DinerMenu() { items=new MenuItem[3]; MenuItem temp; temp=new MenuItem("noodles",20); items[0]=temp; temp=new MenuItem("rice",30); items[1]=temp; temp=new MenuItem("cup cake",5); items[2]=temp; } public MenuItem[] getMenuItems() { return items; } public Iterator createIterator() { return new ArrayIterator(items); } }
另一个集合:PancakeHouseMenu类
import java.util.ArrayList; import java.util.Iterator; /** 使用ArrayList来保存 **/ public class PancakeHouseMenu implements Menu { ArrayList items; public PancakeHouseMenu() { items=new ArrayList(); items.add(new MenuItem("cake",10)); items.add(new MenuItem("pizza",10)); items.add(new MenuItem("pancake",20)); } public ArrayList getMenuItems() { return items; } public Iterator createIterator() { return items.iterator(); } }
Client类
import java.util.Iterator; import java.util.HashMap; /** Client **/ public class Waitress { HashMap<String,Menu> menus; public Waitress() { menus=new HashMap<String,Menu>(); } public void addMenu(String name,Menu menu) { menus.put(name,menu); } public void printMenu() { for(String key:menus.keySet()) { Menu menu=menus.get(key); System.out.println(key); Iterator iterator=menu.createIterator(); while(iterator.hasNext()) { MenuItem menuItem=(MenuItem)iterator.next(); System.out.println(menuItem); } } } }
Waitress类不需要知道它存储的集合是什么,只需要运用Iterator接口以及Menu接口就可以遍历所有集合了,这时候如果要添加新的集合也只需要再写两个类,一个实现Menu接口,一个实现Iterator接口即可。Menu接口有点类似于抽象工厂,负责实例化Iterator对象。
由此我们引出了一个设计原则——“单一职责原则”,意思是,一个类应该只有一个引起它变化的原因,一个类应该只有一个职责。像上面的例子,DinerMenu只需要管理好MenuItem即可,对它的遍历是由ArrayIterator来帮它实现,如果对于遍历有需要修改的,也只需要修改ArrayIterator就可以了。