Iterator(迭代器) 行为型 对象 1
Intent_意图2
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示
Motivation_动机3
用同一种方法遍历包含不同类型数据的整合对象
Applicability_适用性4
遍历 一个聚合对象
Structure_结构5
Participants_参与者6
- Iterator(抽象迭代器) 定义访问和遍历聚合元素的接口
- ConcreteIterator(具体迭代器) 实现抽象迭代器接口中所定义的方法
- Aggregate(抽象聚合) 定义创建迭代器对象的接口
- ConcreteAggregate(具体聚合) 实现抽象聚合类接口,返回一个具体迭代器的实例
- Client(客户) 持有对聚集及其迭代对象的引用,调用迭代子对象的迭代接口,也有可能通过迭代子操作聚集元素的增加和删除
Collaborations_协作7
- Iterator定义访问和遍历聚合元素的接口
->通常包含hasNext()、first()、next()等方法 - ConcreteIterator实现Iterator中所定义的方法,完成对聚合对象的遍历,并记录遍历过程中游标的位置
- Aggregate定义操作聚合对象以及创建迭代器对象的接口
->聚合对象的操作包括存储、添加、删除等 - ConcreteAggregate实现Aggregate的接口,返回一个ConcreteIterator的实例
Comsequences_结果8
- 优点
支持以不同的方式遍历 一个聚合对象
简化了聚合类
在同一个聚合上可以有多个遍历 - 缺点
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,哦单独的个数成对增加,在一定程度上增加了系统的复杂性 - 用途
访问一个聚合对象的内容而无须暴露它的内部表示
需要为聚合对象提供多种遍历方式
为遍历 不同的聚合结构提供一个统一的接口
Implementation/Sample Code_实现/范例代码910
Implementation
Iterator
public interface Iterator {
// 是否还有下一个元素
public boolean hasNext();
// 获取当前元素,并将游标指向下一元素
public Object next();
// 移除元素
public void remove();
}
ConcreteIterator
public class ConcreteIterator implements Iterator {
private ConcreteAggregate agg;
int position = 0;
public ConcreteIterator(ConcreteAggregate agg) {
this.agg = agg;
}
@Override
public boolean hasNext() {
if (position >= agg.size() || agg.get(position) == null) {
return false;
}
return true;
}
@Override
public Object next() {
Object object = agg.get(position);
position = position + 1;
return object;
}
@Override
public void remove() {
if (position <= 0) {
throw new IllegalStateException("You can't remove an item until you've done at least one next()");
}
if (agg.get(position - 1) != null) {
for (int i = position - 1; i < (agg.size() - 1); i++) {
agg.set(i, agg.get(i + 1));
}
}
}
}
Aggregate
public interface Aggregate {
public Iterator createIterator();
}
ConcreteAggregate
public class ConcreteAggregate {
private Object[] objArray = null;
public ConcreteAggregate(Object[] objArray) {
this.objArray = objArray;
}
public Iterator createIterator() {
return new ConcreteIterator(this);
}
public Object get(int index) {
if (index < objArray.length) {
return objArray[index];
} else {
return null;
}
}
public void set(int index, Object obj) {
if (index < objArray.length) {
objArray[index] = obj;
} else {
throw new IllegalStateException("Array index out of bounds exception");
}
}
public int size() {
return objArray.length;
}
}
Sample Code
Iterator
public interface Iterator {
boolean hasNext();
Object next();
}
ConcreteIterator
public class DinnerMenuIterator implements Iterator {
MenuItem[] list;
int position = 0;
public DinnerMenuIterator(MenuItem[] list) {
this.list = list;
}
@Override
public boolean hasNext() {
if (position >= list.length || list[position] == null) {
return false;
}
return true;
}
@Override
public Object next() {
MenuItem menuItem = list[position];
position = position + 1;
return menuItem;
}
}
public class BreakfastMenuIterator implements Iterator {
ArrayList menuItems;
int position = 0;
public BreakfastMenuIterator(ArrayList menuItems) {
this.menuItems = menuItems;
}
@Override
public boolean hasNext() {
if (position >= menuItems.size() || menuItems.get(position) == null) {
return false;
}
return true;
}
@Override
public Object next() {
MenuItem menuItem = (MenuItem) menuItems.get(position);
position = position + 1;
return menuItem;
}
}
Aggregate
public interface Menu {
public Iterator createIterator();
}
ConcreteAggregate
public class DinerMenu implements Menu {
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
MenuItem[] menuItems;
public DinerMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);
addItem("BLT", "Bacon with lettuce * tomato on whole wheat", false, 2.99);
addItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29);
addItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05);
}
public void addItem(String name, String description, boolean vegetarian, double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if (numberOfItems >= MAX_ITEMS) {
System.err.println("Sorry, menu is full! Can't add item to menu");
} else {
menuItems[numberOfItems] = menuItem;
numberOfItems = numberOfItems + 1;
}
}
@Override
public Iterator createIterator() {
return new DinnerMenuIterator(menuItems);
}
}
public class BreakfastMenu implements Menu {
ArrayList menuItems;
BreakfastMenu() {
menuItems = new ArrayList();
addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);
addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);
addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true,3.59);
}
public void addItem(String name, String description, boolean vegetarian, double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
@Override
public Iterator createIterator() {
return menuItems.iterator();
}
}
Client
public class Waitress {
Menu breakfastMenu;
Menu dinnerMenu;
Menu[] menus;
Waitress(Menu breakfastMenu, Menu dinnerMenu) {
this.breakfastMenu = breakfastMenu;
this.dinnerMenu = dinnerMenu;
}
public void printMenu() {
Iterator breakfastIterator = breakfastMenu.createIterator();
Iterator dinnerIterator = dinnerMenu.createIterator();
System.out.println("MENU\n----\nBREAKFAST");
printMenu(breakfastIterator);
System.out.println("\nDINNER");
printMenu(dinnerIterator);
}
private void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
System.out.println(menuItem.getName() + ", ");
System.out.println(menuItem.getPrice() + " -- ");
System.out.println(menuItem.getDescription());
}
}
}
Other
public class MenuItem {
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name, String description, boolean vegetarian, double price) {
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public boolean isVegetarian() {
return vegetarian;
}
public double getPrice() {
return price;
}
}
Known Uses_已知应用11
Related Patterns_相关模式12
模式分类归属 ↩︎
意图:描述该模式的作用,以及该模式的定义 ↩︎
动机:给出了问题以及如何解决这个问题的具体场景 ↩︎
适用性:描述模式可以被应用在什么场合 ↩︎
结构:提供了图示,显示出参与此模式的类之间的关系 ↩︎
参与者:描述在此设计中所涉及到的类和对象在模式中的责任和角色 ↩︎
协作 :告诉参与者如何在此模式中合作 ↩︎
结果:描述采用此模式之后可能产生的效果,好的与不好的 ↩︎
实现:提供了在实现该模式时需要使用的技巧,以及应该小心面对的问题 ↩︎
范例代码:提供代码的片段 ↩︎
已知应用:用来描述已经在真实系统中发现的模式例子 ↩︎
相关模式:描述了此模式和其他模式之间的关系 ↩︎