设计模式 | 迭代器模式(iterator)
定义:
提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
结构:(书中图,侵删)
一个抽象的聚合类
若干个具体的聚合类,有一个生成迭代器的方法(相当于实现java的Iterable接口)
一个抽象的迭代器,定义了迭代所必须的方法
若干个具体的迭代器
来学习一下java中结构
《Java编程思想》中,有关集合的类图(应该是java5的,整体结构应该变化不大):
感觉太复杂了,看起来头疼,自己看源码画了一个和迭代器有关的类图(以ArrayList为例,java8):
实例:
就来仿照一个arraylist吧,Iterator接口就不用写了,java已经有了。
为了简化代码量,List接口还是自己写一个。
抽象List接口:
package designpattern.iterator; import java.util.Iterator; public interface MyList<E> extends Iterable<E> {// 为了客户端直接通过接口使用foreach方法 void set(E e, int index); E get(int index); void remove(int index);// 数组实现,有点麻烦,就不写了 void changeIterator(Iterator iterator); int getSize(); }
ArrayList实现(并不能扩展长度):
package designpattern.iterator; import java.util.Iterator; public class MyArrayList<E> implements MyList<E>, Iterable<E> { E[] data; private int size; Iterator<E> iterator; public MyArrayList(E[] data) { super(); this.data = data; size = data.length; iterator = new MyInteratorAsc<>(this);// 默认使用正序迭代器 } @Override public void set(E e, int index) { if (index < size) { data[index] = e; } else { System.out.println(index + "大于数组大小"); } } @Override public E get(int index) { return data[index]; } @Override public Iterator<E> iterator() { return iterator; } @Override public void remove(int index) { throw new UnsupportedOperationException("暂未实现"); } @Override public int getSize() { return size; } @Override public void changeIterator(Iterator iterator) { this.iterator = iterator; } }
正序迭代器:
package designpattern.iterator; import java.util.Iterator; public class MyInteratorAsc<E> implements Iterator<E> { MyList<E> myList; public MyInteratorAsc(MyList<E> myList) { super(); this.myList = myList; this.current = 0; } int current; @Override public boolean hasNext() { if (current < myList.getSize()) { return true; } else { return false; } } @Override public E next() { return myList.get(current++); } }
倒序迭代器:
package designpattern.iterator; import java.util.Iterator; public class MyInteratorDesc<E> implements Iterator<E> { MyList<E> myList; public MyInteratorDesc(MyList<E> myList) { super(); this.myList = myList; this.current = myList.getSize() - 1; } int current; @Override public boolean hasNext() { if (current >= 0) { return true; } else { return false; } } @Override public E next() { return myList.get(current--); } }
客户端:
package designpattern.iterator; public class Client { public static void main(String[] args) { MyList<String> myList = new MyArrayList<>(new String[4]); myList.set("鼠", 0); myList.set("牛", 1); myList.set("虎", 2); myList.set("兔", 3); myList.set("龙", 4); for (String string : myList) { System.out.println(string); } System.out.println("-------换成倒序-------"); myList.changeIterator(new MyInteratorDesc<>(myList)); for (String string : myList) { System.out.println(string); } } }
结果输出:
4大于数组大小 鼠 牛 虎 兔 -------换成倒序------- 兔 虎 牛 鼠
总结:
自己去实现会发现很多的问题,迭代器几乎天天都在用,实在不知道该总结些什么。
就用书中的原话吧:
迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。