设计模式之迭代器模式
迭代器模式:
迭代器模式(Iterator Pattern) 又称为游标模式(Cursor Pattern) , 它提供一种顺序访问集合/容器对象元素的方法,而又无须暴露集合内部表示。迭代器模式可以为不同的容器提供一致的遍历行为,而不用关心容器内容元素组成结构,属于行为型模式。
提供一种顺序访问集合/容器对象元素的方法,而又无须暴露集合内部表示,迭代器模式的本质是抽离集合对象迭代行为到迭代器中,提供一致访问接口。
迭代器模式的应用场景:
迭代器模式在我们生活中应用的得也比较广泛,比如物流系统中的传送带,不管传送的是什么物品,都被打包成一个一个的箱子并且有一个统一的二维码。这样我们不需要关心箱子里面是啥,我们在分发时只需要一个一个检查发送的目的地即可。再比如,我们平时乘坐交通工具,都是统一刷卡或者刷脸进站,而不需要关心是男性还是女性、是残疾人还是正常人等个性化的信息。
我们把多个对象聚在一起形成的总体称之为集合(Aggregate) , 集合对象是能够包容一组对象的容器对象。不同的集合其内部元素的聚合结构可能不同,而迭代器模式屏蔽了内部元素获取细节,为外部提供一致的元索访问行为,解耦了元素迭代与集合对象间的耦合,并且通过提供不同的迭代器,可以为同个集合对象提供不同顺序的元索访问行为,扩展了集合对象元索迭代功能,符合开闭原则。迭代器模式适用于以下场景:
- 访问一个集合对象的内容而无需暴露它的内部表示;
- 为遍历不同的集合结构提供一个统一的访问接口。
迭代器模式主要包含四种角色:
- 抽象迭代器(Iterator) :抽象迭代器负责定义访问和遍历元素的接口;
- 具体迭代器(Concrete lterator) :提供具体的元素遍历行为;
- 抽象容器(Aggregate) :负责定义提供具体迭代器的接口;
- 具体容器(Concrete Aggregate) :创建具体迭代器。
手写自定义的迭代器:
总体来说,迭代器模式还是非常简单的。我们以课程为例,下面我们自己创建一个课程的集合,集合中的每一个元素就是课程对象,然后自己手写一个迭代器,将每一个课程对象的信息读取出来,首先创建课程Course类:
public class Course { private String name; public Course(String name) { this.name = name; } public String getName() { return name; } }
然后创建自定义迭代器接口 Iterator
public interface Iterator<E> { E next(); boolean hasNext(); }
然后创建自定义的课程集合接口 ICourseAggregate
public interface ICourseAggregate { void add(Course course); void remove(Course course); Iterator<Course> iterator(); }
然后分别实现这两个接口:
public class IteratorImpl<E> implements Iterator<E> { private List<E> list; private int cursor; private E element; public IteratorImpl(List<E> list) { this.list = list; } public E next() { System.out.print("当前位置 " + cursor + " : "); element = list.get(cursor); cursor ++; return element; } public boolean hasNext() { if(cursor > list.size() - 1){ return false; } return true; } } public class CourseAggregateImpl implements ICourseAggregate { private List courseList; public CourseAggregateImpl() { this.courseList = new ArrayList(); } public void add(Course course) { courseList.add(course); } public void remove(Course course) { courseList.remove(course); } public Iterator<Course> iterator() { return new IteratorImpl<Course>(courseList); } }
然后编写测试类:
public class Test { public static void main(String[] args) { Course java = new Course("Java架构"); Course javaBase = new Course("Java基础"); Course design = new Course("设计模式"); Course ai = new Course("人工智能"); ICourseAggregate aggregate = new CourseAggregateImpl(); aggregate.add(java); aggregate.add(javaBase); aggregate.add(design); aggregate.add(ai); System.out.println("===========课程列表=========="); printCourse(aggregate); aggregate.remove(ai); System.out.println("===========删除操作之后的课程列表=========="); printCourse(aggregate); } private static void printCourse(ICourseAggregate aggregate) { Iterator<Course> i = aggregate.iterator(); while (i.hasNext()){ Course course = i.next(); System.out.println("《" + course.getName() + "》"); } } }
优点:
- 多态迭代:为不同的聚合结构提供一致的遍历接口,即一个迭代接口可以访问不同的集合对象;
- 简化集合对象接口:迭代器模式将集合对象本身应该提供的元素迭代接口抽取到了迭代器中,使集合对象无须关心具体迭代行为;
- 元素迭代功能多样化:每个集合对象都可以提供一个或多个不同的迭代器,使的同种元索聚合结构可以有不同的迭代行为;
- 解耦迭代与集合:迭代器模式封装了具体的迭代算法,迭代算法的变化,不会影响到集合对象的架构
缺点:
- 对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐。
- 在日常开发当中,我们几乎不会自己写迭代器。除非我们需要定制一个自己实现的数据结构对应的迭代器,不然常规的API足够用了