- 迭代器模式
提供一种方法来顺序访问一个聚合对象中各个元素,而又无需暴露该对象的内部表示。
首先解释下什么叫做聚合对象,就)是可以存储多个成员的元素或者是对象的的类。一般情况下,聚合对象主要是用来存储数据和和遍历书,这样就可以联想到JAVA中的list,数组,HashSet等等。这些确实都是聚合对象。这里就存在个问题,就是当我们要遍历不同类型的聚合对象时,就要清楚的知道其结构,毕竟不同结构的聚合对象遍历的方式有区别。但是如果我们使用了迭代器模式,就不需要知道每个聚合对象的内部结构,而可以很方便快捷的遍历不同聚合对象的内部成员。 - 迭代模式示例图
- 迭代器模式设计角色:
- 抽象迭代器角色:这是迭代器模式中最终要的角色,一般为抽象类或者是接口的形式。从经验来说一般包括三个方法
hasNext()
、next()
、remove()
三个方法。该角色定义了访问和遍历元素的接口。 - 具体迭代器角色:继承或者实现了抽象迭代器角色。并且实现了其中的方法。
- 抽象聚合角色:一般是一个接口,用于定义创建迭代器的方法。
- 具体聚合角色:实现抽象聚合角色,并且创建相应的迭代器。
- 迭代器模式的示例代码
场景:一家早餐馆收购了一家晚餐馆,合并后发现两家店的菜单系统由于之前设计的问题,存在相当大的差异,早餐店使用的是数组作为存储结构,晚餐店使用的是list作为存储结构。现在需求是打印出两个菜单。
抽象迭代器角色:
public interface Iterator {
boolean hasNext();
Object next();
void remove(Object item);
}
具体迭代器角色:
早餐厅迭代器角色:
public class BreakfastIterator implements Iterator {
private Object[] items = new Object[5];
private int position;
public BreakfastIterator(Object[] items) {
this.items = items;
this.position = 0;
}
@Override
public boolean hasNext() {
if (position<items.length){
return true;
}
return false;
}
@Override
public Object next() {
Object obj = items[position];
if (position>5){
throw new IndexOutOfBoundsException("菜单只有五项!");
}else{
position++;
}
return obj;
}
@Override
public void remove(Object item) {
Object[] objects = new Object[5];
for (int i = 0; i <items.length ; i++) {
if (!items[i].equals(item)){
objects[i] = items[i];
}
}
items = objects;
}
}
晚餐厅具体迭代器角色:
public class DinnerIterator implements Iterator {
private List<Object> list;
private int position ;
public DinnerIterator(List<Object> list) {
this.list = list;
this.position = 0;
}
@Override
public boolean hasNext() {
if (position < list.size()){
return true;
}
return false;
}
@Override
public Object next() {
Object menuItem = list.get(position);
position++;
return menuItem;
}
@Override
public void remove(Object item) {
list.remove(item);
}
}
抽象聚合角色:
public interface Aggregate {
Iterator createIterator();
}
具体聚合角色:
public class BreakFastMeun implements Aggregate {
private MenuItem[] menuItems ;
private int num=0;
public BreakFastMeun() {
menuItems = new MenuItem[3];
addMeunItem(new MenuItem("包子",1.5f));
addMeunItem(new MenuItem("馒头",1f));
addMeunItem(new MenuItem("粽子",5f));
}
@Override
public Iterator createIterator() {
return new BreakfastIterator(menuItems);
}
public void addMeunItem(MenuItem menuItem){
if (num >= menuItems.length) {
System.err.println("sorry,menu is full!can not add another item");
} else {
menuItems[num] = menuItem;
num++;
}
}
}
public class DinnerMeun implements Aggregate {
private List list;
public DinnerMeun() {
list = new ArrayList();
add(new MenuItem("麻婆豆腐",18f));
add(new MenuItem("土豆丝",12f));
add(new MenuItem("红烧肉",30f));
}
public void add(MenuItem menuItem){
list.add(menuItem);
}
@Override
public Iterator createIterator() {
return new DinnerIterator(list);
}
}
菜单项:
public class MenuItem {
private String name;
private float price;
public MenuItem(String name, float price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "MenuItem{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
招待者角色(测试主函数):
public class Waitress {
public static void main(String[] args) {
BreakFastMeun breakFastMeun = new BreakFastMeun();
DinnerMeun dinnerMeun = new DinnerMeun();
Iterator iteratorForB = breakFastMeun.createIterator();
Iterator iteratorForD = dinnerMeun.createIterator();
List<Iterator> iterators = new ArrayList<Iterator>();
iterators.add(iteratorForB);
iterators.add(iteratorForD);
for (int i = 0; i <iterators.size() ; i++) {
while (iterators.get(i).hasNext()){
System.out.println(iterators.get(i).next().toString());
}
}
}
}
5.迭代器模式的优缺点:
优点:
- 它支持以不同的方式遍历一个聚合对象
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。符合JAVA的开闭原则。
缺点:
新增迭代器和聚合类是一对一的关系,这样设计就会导致成对增加,会导致类过多,增加系统的复杂度。
JAVA内置的迭代器
1.对于JAVA的众多聚合类型的数据,其本身就自带内部迭代器,例如list,使用其内部迭代器也可以遍历其中的具体内容,而不需要用for循环来操作。其内部迭代器使用方式如下,这里只做简单说明:
public class MainTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("123");
list.add("456");
list.add("789");
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}