迭代这个词不陌生,List,Set,Map等等都有迭代器。所谓的迭代器就是访问该聚合对象中的各个元素。比如链表遍历。如果将该链表的创建和遍历都放在一个类中那肯定是不行的,如果要更改遍历方法就得修改源码,这违反了开闭原则。如果类不提供遍历方法,由用户自己实现也是不可以的,因为这样会暴露聚合类的内部表示,对数据是不安全的,所以可以在客户端和聚合类之间放置一个迭代器,客户只需要调用迭代器就可以完成聚合类数据的遍历,任何的遍历都交给迭代器来操作,可以在迭代器内定义许多不同的遍历方法。
一个迭代器模式有4个具体角色 抽象聚合,具体聚合,抽象迭代器,具体迭代器。聚合类符合添加,删除聚合对象以及创建迭代器。迭代器依赖于聚合,定义访问和遍历聚合元素的方法。
抽象聚合
public interface DiyList { void add(Object o); void remove(Object o); DiyIrerator getDiyIrerator(); }
具体聚合
public class DiyListImpl implements DiyList { private ArrayList<Object> Objects=new ArrayList<>(); @Override public void add(Object o) { Objects.add(o); } @Override public void remove(Object o) { Objects.remove(o); } @Override public DiyIrerator getDiyIrerator() { return (new ConcreteIterator(Objects) ); } }
抽象迭代器
public interface DiyIrerator { Object first(); Object next(); boolean hasNext(); }
具体迭代器
public class ConcreteIterator implements DiyIrerator { private ArrayList<Object> list=null; int index=-1; public ConcreteIterator(ArrayList<Object> list) { this.list = list; } @Override public Object first() { return list.get(index+1); } @Override public Object next() { Object o=null; if(hasNext()){ return list.get(++index); } return null; } @Override public boolean hasNext() { if(list.get(index+1)!=null){ return true; } return false; } }
测试类
public class Client { public static void main(String[] args) { DiyListImpl diyList = new DiyListImpl(); diyList.add("1"); diyList.add("2"); diyList.add("3"); DiyIrerator diyIrerator = diyList.getDiyIrerator(); String first = (String) diyIrerator.first(); System.out.println(first); } }
可以看到,每一个聚合类绑定一个固定的迭代器,对用户来说聚合类内部是未知的,对聚合类来说,迭代方法没有与自己绑定,完全符合开闭原则。修改聚合类的遍历方法只需要修改对应的迭代器类。
应用场景:当需要为聚合对象提供多种可能会更改的遍历方式时,或者需要保护聚合类内部细节时