对于java的集合容器ArrayList我们都有过输出其数据元素的经历,我们写一个for循环然后遍历输出。然后这样做有一个缺点,那就是我们需要了解ArrayList容器内部的数据结构,比如说里面可能保存的是String或者是Int。现在有一个设计模式叫做迭代器模式,让用户通过特定的接口访问容器的数据,不需要了解容器内部的数据结构。
一、认识迭代器模式
概念:迭代子模式可以顺序的访问集合内部的元素而不必知道集合内部表象。
可能我们会问,集合里面有迭代接口Iterator,为什么还要自己再去设计一个迭代器呢?这不是多此一举嘛。
为此我们先来看看使用迭代器有什么坏处吧。先看下面一段代码:
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
//添加元素
for (int i = 0; i < 5; i++) {
list.add("index"+i);
}
Iterator<String> it = list.iterator();//获取迭代器
//遍历元素
while(it.hasNext()) {
if(it.next().equals("index3")) {
list.remove(it.next());
}
}
}
}
我们添加5个元素,然后在for循环中去遍历,当遍历到index4的时候,我们移除它。看起来好像代码没有什么问题,但是我们运行一下。你就会发现出现下列错误。
1-迭代器模式.png
也就是说我们不能在迭代元素的时候进行增删改的操作。而且还有一个重要的原因,那就是我们在迭代元素的时候其实是会有可能修改集合容器中的元素的,这带来了极大的不安全。因为你不知道用户访问这个数据要执行什么操作。于是乎,迭代器模式出现了,能为我们很好的解决上面的问题。
我们来看看迭代模式的类图:
3-迭代器类图.jpg从上面可以看到这里包含了4个角色,我们分别来介绍一下:
(1)Aggregate集合:创建迭代子的接口; (2)ConcreteAggregate 具体集合:实现迭代子接口; (3)Iterator 迭代子接口:给出迭代每个元素的接口; (4)ConcreteIterator 具体迭代子:实现迭代方法。
我们代码实现一下。
二、代码实现
第一步:定义抽象容器
public abstract class Aggregate {
//这是我们自己的迭代器
public abstract MyIterator iterator();
public abstract Object getElement(int index);
public abstract int size();
}
第二步:定义ConcreteAggregate 具体集合容器
public class ConcreteAggregate extends Aggregate{
private List<String> list=new ArrayList<>();
public ConcreteAggregate() {
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
}
@Override
public MyIterator iterator() {
return new ConcreteIterator(this);
}
public Object getElement(int index){
return list.get(index);
}
public int size(){
return list.size();
}
}
第三步:Iterator 迭代子接口
public interface MyIterator {
//移动到第一个对象
public void first();
//是否最后
public boolean isLast();
//移动下一个
public void next();
//当前对象
public Object current();
}
第四步:ConcreteIterator 具体迭代子
public class ConcreteIterator implements MyIterator{
Aggregate agg;
int size=0;
int index=0;
public ConcreteIterator(Aggregate agg) {
this.agg=agg;
size=agg.size();
}
@Override
public void first() {
index=0;
}
@Override
public boolean isLast() {
return index>=size;
}
@Override
public void next() {
if(index<size){
index++;
}
}
@Override
public Object current() {
return agg.getElement(index);
}
}
最后我们在客户端调用一下
public class Test {
public static void main(String[] args) {
Aggregate agg=new ConcreteAggregate();
MyIterator iterator = agg.iterator();
while(!iterator.isLast()){
System.out.println(iterator.current());
iterator.next();
}
}
}
三、总结
说实话一般情况下,迭代器模式还是很少见的,文章一开始给出了迭代器的缺点,但是我们稍微改变一下就能够避免,也就是说java提供迭代器基本上就能满足我们的要求。还有一点需要注意,迭代器模式适合集合同生共死的。
宣传页_副本2_副本.jpg
网友评论