设计模式之迭代器模式
1.定义/概念
迭代器模式是Java和.Net编程环境中非常常用的设计模式。这种设计模式用于顺序访问集合对象的元素要知道集合对象的底层表示。迭代器模式属于行为型模式
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
2.角色和定义
● Iterator抽象迭代器
抽象迭代器负责定义访问和遍历元素的接口,而且基本上是有固定的3个方法:first()获得第一个元素,next()访问下一个元素,isDone()是否已经访问到底部(Java叫做hasNext()方法)。
● ConcreteIterator具体迭代器
具体迭代器角色要实现迭代器接口,完成容器元素的遍历。
● Aggregate抽象容器
容器角色负责提供创建具体迭代器角色的接口,必然提供一个类似createIterator()这样的方法,在Java中一般是iterator()方法。
● Concrete Aggregate具体容器
具体容器实现容器接口定义的方法,创建出容纳迭代器的对象。
ps:迭代器模式已经被淘汰,java中已经把迭代器运用到各个聚集类(collection)中了,使用java自带的迭代器就已经满足我们的需求了。
3.表现形式
定义一个迭代器的抽象,这里使用接口定义
public interface MyIterator {
public void first();//将游标指向第一个元素
public void next();//将游标指向下一个元素
public boolean hasNext();//判断是否有下一个元素
public boolean isFirst();//判断是否是第一个元素
public boolean isLast();//判断是否是最后一个元素
Object getCurrentObj();//获取当前对象
}
然后自定义一个一个聚集类,这里直接使用一个class来定义了。在聚集内部,使用内部类的方式来定义迭代器的具体表现
import java.util.ArrayList;
import java.util.List;
//自定义聚集类
public class ConcreteMyAggregate {
private List<Object> list = new ArrayList<>();
public void addObject(Object obj){
this.list.add(obj);
}
public void removeObject(Object obj){
this.list.remove(obj);
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
//获得迭代器
public MyIterator createIterator(){
return new ConcreteIterator();
}
//使用内部类来定义迭代器,好处就是可以直接使用外部类的属性
private class ConcreteIterator implements MyIterator{
private int cursor;//定义一个迭代器游标
@Override
public void first() {
cursor = 0;
}
@Override
public void next() {
if (cursor<list.size()) {
cursor++;
}
}
@Override
public boolean hasNext() {
//如果游标<list的大小,则说明还有下一个
if (cursor<list.size()) {
return true;
}
return false;
}
@Override
public boolean isFirst() {
return cursor==0?true:false;
}
@Override
public boolean isLast() {
//判断游标是否是容器的最后一个
return cursor==(list.size()-1)?true:false;
}
@Override
public Object getCurrentObj() {
return list.get(cursor);//获取当前游标指向的元素
}
}
}
客户端测试类
public static void main(String[] args) {
ConcreteMyAggregate cma = new ConcreteMyAggregate();
cma.addObject("1111");
cma.addObject("222");
cma.addObject("333");
cma.addObject("444");
MyIterator iterator = cma.createIterator();
cma.removeObject("111");//如果删除一个元素的话,迭代的时候也同样会被删除
while (iterator.hasNext()) {
System.out.println(iterator.getCurrentObj());//获取当前对象
iterator.next();//将游标向下移
}
}
4.迭代器优缺点
优点
(1)当修改魔偶一个遍历算法时不会影响其他的遍历算法
(2)迭代器模式支持以不同的方式遍历同一个聚合,复杂的聚合可用多种方式进行遍历。
(3)当修改被遍历的聚合结构代码时,如果该聚合结构没有改变,则相应的遍历算法代码也不需要改变。
(4)迭代器简化了聚合的接口,有了迭代器的遍历接口,聚合本身就不需要类似的遍历接口了,这样就简化了聚合的接口。
缺点
对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合。
总的来说: 迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的Collection,List、Set、Map等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器。
5.迭代器模式应用的场景及意义
(1)访问一个聚合对象的内容而无需暴露它的内部表示
(2)支持对聚合对象的多种遍历
(3)为遍历不同的聚合结构提供一个统一的接口