初学迭代器设计模式,一直不怎么理解,希望通过写篇博客加强理解。
我的理解是,迭代器设计模式可以解决这个问题。如果我有一个自已定义的类,这个类有当作容器的功能,比如里面有一个属性是Set,然后我想要遍历被放入这个容器类的一组ADT对象,而无需关注容器的具体类型,这时就可以使用迭代器设计模式了。
我们需要关注两个接口,Iterable和Iterator。这两个接口的大致结构如下:
public interface Iterable<T> {
...
Iterator<T> iterator();
}
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
让自己的集合类实现Iterable接口,并实现自己独特的Iterator迭代器(hasNext,next,remove),允许客户端利用这个迭代器进行显示或隐式的迭代遍历:
for (E e : collection) {...}
Iterator<E> iter=collection.iterator();
while (iter.hasNext()) {...}
下面看一个具体的例子。比如我们要造一个停车场ParkingField,这是一个接口,它的实现类是ConcreteParkingField。然后车位的类叫Lot,停进去的东西有汽车,摩托车等,所以有一个接口Parkable。下面看看怎么实现迭代器。
我们首先需要给停车场这个容器提供遍历的功能,所以用ParkingField继承接口Iterable,再用ConcreteParkingField实现ParkingField。r然后需要提供一个迭代器,用ParkingIterator来实现接口Iterator。代码框架大致如下(里面的方法和属性不是重点,所以我把大部分的属性用…代替,重点是和迭代器相关的东西):
ParkingField继承接口Iterable
public interface ParkingField extends Iterable<String> {
public static ParkingField create(int[] nos, int[] widths) throws Exception {
return new ConcreteParkingField(nos, widths);
}
public static ParkingField create(Map<Integer, Integer> lots) throws Exception {
return new ConcreteParkingField(lots);
}
public void parking(String type, String plate, int width, int num, String[] extraRegistrationInfo) throws Exception;
public void parking(String type, String plate, int width, String[] extraRegistrationInfo);
public double depart(String plate) throws Exception;
public Map<Integer, String> status();
public int getNumberOfLots();
public boolean isLotInParkingField(int num, int width);
public boolean isEmpty();
int getLotWidth(int num) throws Exception;
}
ConcreteParkingField实现接口ParkingField
public class ConcreteParkingField implements ParkingField {
private final ...
private final Map<Lot, Parkable> status = new HashMap<>();
private final ...
public ConcreteParkingField(Map<Integer, Integer> lotsInfo) throws Exception {...}
public ConcreteParkingField(int[] nos, int[] widths) {...}
@Override
public void parking(String type, String plate, int width, int num, String[] extraRegistrationInfo) throws Exception {...}
@Override
public void parking(String type, String plate, int width, String[] extraRegistrationInfo) {...}
@Override
public double depart(String plate) throws Exception {...}
@Override
public Map<Integer, String> status() {...}
@Override
public int getNumberOfLots() {...}
@Override
public boolean isLotInParkingField(int num, int width) {...}
@Override
public boolean isEmpty() {...}
@Override
public int getLotWidth(int num) throws Exception {...}
@Override
public String toString() {...}
// 重点是这个。。。返回一个迭代器
@Override
public Iterator<String> iterator() {
return new ParkingIterator(this.status);
}
ParkingIterator来实现接口Iterator
注意,正常情况下Iterator的泛型应该是Parkable,为了不给ParkingField和client泄露Parkable,改成了String。
public class ParkingIterator implements Iterator<String> {
private final ...
private final ...
private int count = 0;
public ParkingIterator(...) {
...
}
@Override
public boolean hasNext() {
return count < ....size();
}
@Override
public String next() {
...
count ++;
...
}
@Override
public void remove() {
...
}
}
总的来说,迭代器模式让数据处理逻辑和内部数据管理分离,用一种更安全的方式进行遍历。此外,还可以还可以控制内部数据的顺序,这上面的例子中,于ParkingIterator的构造方法中加入一个排序即可。
以上,如有错误,恳请斧正。