设计模式学习笔记之迭代器模式
迭代器模式
提供一种方法顺序访问一个聚合对象中的各个对象,而不暴露其内部的表示。
把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
角色:
容器角色:负责提供创建具体迭代器角色的接口;
具体容器角色:实现创建具体迭代器角色的接口, 这个具体迭代器角色与该容器的结构相关;
迭代器角色(Iterator):负责定义访问和遍历元素的接口;
具体迭代器角色(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代。
优点:
1、简化了遍历方式,对于对象集合的遍历,还是比较麻烦的,对于数组或者有序列表,我们尚可以通过游标来取得,但用户需要在对集合了解很清楚的前提下,自行遍历对象,但是对于hash表来说,用户遍历起来就比较麻烦了。而引入了迭代器方法后,用户用起来就简单的多了。
2、可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。
3、封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心。
缺点:
1、对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合。
场景:
迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的Collection,List、Set、Map等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器。
但是,由于容器与迭代器的关系太密切了,所以大多数语言在实现容器的时候都给提供了迭代器,并且这些语言提供的容器和迭代器在绝大多数情况下就可以满足我们的需要,所以现在需要我们自己去实践迭代器模式的场景还是比较少见的,我们只需要使用语言中已有的容器和迭代器就可以了。
/**
* 迭代器角色
* */
public interface Iterator {
boolean hasNext();
Object next();
}
|
/**
* 菜单项
* */
public class MenuItem {
String name;
String description;
// 是否为素食
boolean vegetarion;
double price;
public MenuItem(String name, String description, boolean vegetarion, double price) {
this.name = name;
this.description = description;
this.vegetarion = vegetarion;
this.price = price;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public boolean isVegetarion() {
return vegetarion;
}
public double getPrice() {
return price;
}
}
|
/**
* 餐厅菜单
* */
public class DinerMenu {
static final int MAX_ITEMS = 6;
int numOfItems = 0;
MenuItem[] items;
public DinerMenu(MenuItem[] items){
this.items = items;
}
public Iterator createIterator() {
return new DinerMenuIterator(items);
}
}
|
public class PancakeHouseMenu {
static final int MAX_ITEMS = 6;
int numOfItems = 0;
ArrayList<MenuItem> items;
public PancakeHouseMenu(ArrayList<MenuItem> items){
this.items = items;
}
public Iterator createIterator() {
return new PancakeHouseIterator(items);
}
}
|
/**
* 餐厅菜单迭代器 具体迭代器角色
* */
public class DinerMenuIterator implements Iterator{
MenuItem[] items;
int position = 0;
public DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
public boolean hasNext() {
if(position >= items.length || items[position] == null) {
return false;
}
return true;
}
public Object next() {
MenuItem item = items[position];
position++;
return item;
}
}
|
/**
* 煎饼屋菜单迭代器
* */
public class PancakeHouseIterator implements Iterator{
ArrayList<MenuItem> items;
int position = 0;
public PancakeHouseIterator(ArrayList<MenuItem> items) {
this.items = items;
}
public boolean hasNext() {
if(position >= items.size() || items.get(position) == null) {
return false;
}
return true;
}
public Object next() {
MenuItem item = items.get(position);
position++;
return item;
}
}
|
public class Waitress {
DinerMenu dinerMenu;
PancakeHouseMenu pancakeMenu;
public Waitress(DinerMenu dinerMenu, PancakeHouseMenu pancakeMenu) {
this.dinerMenu = dinerMenu;
this.pancakeMenu = pancakeMenu;
}
public void printMenu() {
Iterator dinerIterator = dinerMenu.createIterator();
Iterator pancakeIterator = pancakeMenu.createIterator();
System.out.println("Diner menu......");
printMenu(dinerIterator);
System.out.println("Pancake House Menu......");
printMenu(pancakeIterator);
}
private void printMenu(Iterator iterator){
MenuItem item;
while(iterator.hasNext()) {
item = (MenuItem) iterator.next();
System.out.print("Name : "+ item.getName() +", ");
System.out.println("Price : "+ item.getPrice());
}
}
}
|
public class Client {
public static void main(String[] args) {
ArrayList<MenuItem> pancakeItems = new ArrayList<MenuItem>();
pancakeItems.add(new MenuItem("干锅土豆" , "", false, 10));
pancakeItems.add(new MenuItem("巫山烤鱼", "", true, 30));
pancakeItems.add(new MenuItem("炝炒土豆丝", "", false, 20));
PancakeHouseMenu pancakeMenu = new PancakeHouseMenu(pancakeItems);
MenuItem[] dinerItems = new MenuItem[3];
dinerItems[0] = new MenuItem("煎饼", "", false, 5);
dinerItems[1] = new MenuItem("绿豆粥", "", false, 3);
dinerItems[2] = new MenuItem("咸菜", "", false, 5);
DinerMenu dinerMenu = new DinerMenu(dinerItems);
Waitress waitress = new Waitress(dinerMenu, pancakeMenu);
waitress.printMenu();
}
}
|
参考资料:《Head First 设计模式》