概念理解
迭代器模式是非常常见的一种行为模式,它能顺序的访问容器中的元素,不用关心容器的内部存储实现。
实例讲解
蛋糕店和中餐厅都有自己的菜单,蛋糕店使用数组存储自己的菜单列表,中餐厅使用List存储自己的菜单列表,现要将两者合并,打印出一份菜单列表出来。
设计一
这种结构是直观的设计,Waiter类不仅需要依赖两个餐厅,还需要知道两个餐厅的具体实现,这样才能打印出菜单。很明显,这种结构系统内部耦合性太强,不利于扩展。
public class CakeHouse {
private MenuItem[] menuItems;
private int count = 0;
private int maxCount = 10;
public CakeHouse() {
menuItems = new MenuItem[maxCount];
}
public void addItem(MenuItem menuItem) {
if (count == maxCount) {
return;
}
menuItems[count++] = menuItem;
}
public int getCount() {
return count;
}
public MenuItem[] getMenuItems() {
return menuItems;
}
public void setMenuItems(MenuItem[] menuItems) {
this.menuItems = menuItems;
}
}
public class DinnerRestaurant {
private List<MenuItem> menuItemList;
public DinnerRestaurant() {
menuItemList = new ArrayList<MenuItem>();
}
public void addItem(MenuItem menuItem) {
menuItemList.add(menuItem);
}
public List<MenuItem> getMenuItemList() {
return menuItemList;
}
public void setMenuItemList(List<MenuItem> menuItemList) {
this.menuItemList = menuItemList;
}
}
public class Waiter {
private CakeHouse house;
private DinnerRestaurant dinnerRestaurant;
public Waiter(CakeHouse cakeHouse,DinnerRestaurant restaurant){
this.house = cakeHouse;
this.dinnerRestaurant = restaurant;
}
public void printAllMenus(){
MenuItem[] menuItems = this.house.getMenuItems();
for(int i =0; i<this.house.getCount();i++){
System.out.println(menuItems[i]);
}
List<MenuItem> menuItemList = this.dinnerRestaurant.getMenuItemList();
for(int i =0; i<menuItemList.size();i++){
System.out.println(menuItemList.get(i));
}
}
}
设计二:使用迭代器
迭代器非常简单,两个餐厅仅需要提供各自的迭代器即可,Waiter类不需要知道两个餐厅的具体存储菜单的方式,仅需要维护一个可以提供迭代器的容器列表。
public interface Iterator<T> {
boolean hasNext();
T next();
}
public interface Container {
Iterator getIterator();
}
public class CakeHouse implements Container {
private MenuItem[] menuItems;
private int count = 0;
private int maxCount = 10;
private int currentIndex = 0;
public CakeHouse() {
menuItems = new MenuItem[maxCount];
}
public void addItem(MenuItem menuItem) {
if (count == maxCount) {
return;
}
menuItems[count++] = menuItem;
}
public int getCount() {
return count;
}
public MenuItem[] getMenuItems() {
return menuItems;
}
public void setMenuItems(MenuItem[] menuItems) {
this.menuItems = menuItems;
}
public Iterator getIterator(){
return new CakeHouseIterator();
}
private class CakeHouseIterator implements Iterator<MenuItem> {
@Override
public boolean hasNext() {
return currentIndex < count;
}
@Override
public MenuItem next() {
return menuItems[currentIndex++];
}
}
}
public class DinnerRestaurant implements Container {
private List<MenuItem> menuItemList;
private int currentIndex = 0;
public DinnerRestaurant() {
menuItemList = new ArrayList<MenuItem>();
}
public void addItem(MenuItem menuItem) {
menuItemList.add(menuItem);
}
public List<MenuItem> getMenuItemList() {
return menuItemList;
}
public void setMenuItemList(List<MenuItem> menuItemList) {
this.menuItemList = menuItemList;
}
public Iterator getIterator(){
return new DinnerIterator();
}
private class DinnerIterator implements Iterator<MenuItem> {
@Override
public boolean hasNext() {
return currentIndex < menuItemList.size();
}
@Override
public MenuItem next() {
return menuItemList.get(currentIndex++);
}
}
}
public class Waiter {
private List<Container> containerList;
public Waiter() {
containerList = new ArrayList<Container>();
}
public void addContainer(Container container) {
containerList.add(container);
}
public void printMenu() {
for(int i =0; i< containerList.size();i++){
Container container = containerList.get(i);
Iterator iterator =container.getIterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
}
总结
jdk中已经存在了迭代器接口Iterator,set,list也实现了迭代器。
迭代器将存储数据和遍历数据的职责分开,增加聚合类仅需提供迭代器,无需修改现有代码。
代码实例参见
https://github.com/jxl198/designPattern/tree/master/iterator