原文地址:http://blog.csdn.net/risky78125/article/details/50443724
设计模式-迭代器模式Interator
概念:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。
下面设计一个例子,演示迭代器模式的使用
例如有下面一种情况,一个餐厅,有两个厨师.一个负责早餐,一个负责午餐.但是呢,两个师傅都非常有个性.一个师傅的菜单 (BreakfastMenu)是用集合(List进行表示的,而另一个师傅的菜单(LunchMenu)是用数组(MenuItem[]).如果此时, 服务员(Waitress)需要向客人展示菜单里的内容就非常的不方便,除非让两个厨师统一.但是之前说过了,师傅太有个性了,就不改.那么下面,使用代 码演示一下.
首先,菜品类:
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;
}
@Override public String toString() { return "MenuItem{" + "name='" + name + '\'' + ", price=" + price + '}';
}
}123456789101112131415161718192021
做早餐的师傅,菜单是用集合形式表示的
public class BreakfastMenu { private List<MenuItem> menuItems; public BreakfastMenu() {
menuItems = new ArrayList<>();
addItem("豆浆", 1.0);
addItem("鸡蛋", 1.0);
addItem("肉包子", 2.5);
addItem("豆腐脑", 2.0);
} private void addItem(String name, double price) {
MenuItem item = new MenuItem(name, price);
menuItems.add(item);
} public List<MenuItem> getMenuItems() { return menuItems;
}
}1234567891011121314151617
做午餐的师傅,菜单是使用数组表示的
public class LunchMenu { private static final int MAX_ITEMS = 3; private MenuItem[] menuItems; private int index; public LunchMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("鸡排饭", 8.0);
addItem("蛋炒饭", 7.0);
addItem("白菜盖饭", 9.0);
} private void addItem(String name, double price) {
MenuItem item = new MenuItem(name, price);
menuItems[index] = item;
index++;
} public MenuItem[] getMenuItems() { return menuItems;
}
}12345678910111213141516171819
此时,服务员的做法如下:
public class Waitress { private BreakfastMenu breakfastMenu; private LunchMenu lunchMenu; public Waitress(BreakfastMenu breakfastMenu, LunchMenu lunchMenu) { this.breakfastMenu = breakfastMenu; this.lunchMenu = lunchMenu;
}
blic void printMenu(){
printBreakfastMenu();
printLunchMenu();
} public void printBreakfastMenu(){
System.out.println("---早餐---");
List<MenuItem> breakfast = breakfastMenu.getMenuItems(); for (int i = 0; i < breakfast.size(); i++) {
System.out.println(breakfast.get(i));
}
} public void printLunchMenu(){
System.out.println("---午餐---");
MenuItem [] lunch = lunchMenu.getMenuItems(); for (int i = 0; i < lunch.length; i++) {
System.out.println(lunch[i]);
}
}
}1234567891011121314151617181920212223242526
执行程序如下:
public class Hotel { public static void main(String[] args) {
BreakfastMenu breakfastMenu = new BreakfastMenu();
LunchMenu lunchMenu = new LunchMenu();
Waitress waitress = new Waitress(breakfastMenu, lunchMenu);
waitress.printMenu();
}
}12345678
可以看到,服务员(Waitress)分别遍历了两种集合,那如果再加个有个性的厨师呢?再来个用Map存储的,是不是还得再写一个遍历?
下面,介绍迭代器(Interator)的用法
首先,创建迭代器接口
public interface Iterator<T> {
boolean hasNext();
T next();
}1234
早餐菜单的实现类如下:
public class BreakfastMenuIterator implements Iterator<MenuItem> {
private List<MenuItem> items; private int index; public BreakfastMenuIterator(List<MenuItem> items) { this.items = items;
}
@Override public boolean hasNext() { if (index < items.size()) return true; return false;
}
@Override public MenuItem next() { return items.get(index++);
}
}12345678910111213141516
午餐菜单实现类如下:
public class LunchMenuIterator implements Iterator<MenuItem> {
private MenuItem [] items; private int index; public LunchMenuIterator(MenuItem[] items) { this.items = items;
}
@Override public boolean hasNext() { if (index < items.length) return true; return false;
}
@Override public MenuItem next() {
MenuItem item = items[index++]; return item;
}
}123456789101112131415161718
然后,分别在BreakfastMenu和LunchMenu类下面公布一个新方法,createInterator()
public class BreakfastMenu {
/** 其余代码未变,省略 */
public Iterator createIterator(){ return new BreakfastMenuIterator(menuItems);
}
}123456
同样,LunchMenu
public class LunchMenu {
/** 其余代码未变,省略 */
public Iterator createIterator(){ return new LunchMenuIterator(menuItems);
}
}123456
修改Waitree类
public class Waitress { private final Iterator breakfastIterator; private final Iterator dinerIterator; public Waitress(BreakfastMenu breakfastMenu, LunchMenu lunchMenu) {
breakfastIterator = breakfastMenu.createIterator();
dinerIterator = lunchMenu.createIterator();
} public void printMenu(){
printBreakfastMenu();
printLunchMenu();
} private void print(Iterator iterator){ while (iterator.hasNext()){
MenuItem item = (MenuItem) iterator.next();
System.out.println(item.toString());
}
} public void printBreakfastMenu(){
System.out.println("---早餐---");
print(breakfastIterator);
} public void printLunchMenu(){
System.out.println("---午餐---");
print(dinerIterator);
}
}1234567891011121314151617181920212223242526272829
执行程序的代码无改动.
可以看到,此时Waitree类完全不用考虑菜单的类型,关心的只是是否实现了迭代器的接口.而其他的菜单类,只是添加了一个方法而已,对厨师来说,那只是小事儿一桩.
上面是咱们自己创建了一个迭代器,实际上在java中,系统有Interator这个接口,并且List/Map等集合类也都是有直接的方法来提供迭代器,例如:
List<MenuItem> breakfastMenus = new ArrayList<>();
java.util.Iterator listIterator = breakfastMenus.iterator();
Map<String,MenuItem> map = new HashMap<>();