模式说明

对于由多个相同元素聚合而成的对象,需要遍历内部元素时,最直接的做法是在客户端通过一个for循环来执行遍历操作。该做法的缺点是对客户端暴露了聚合对象的内部,且增加了客户端的负担。另一种做法是在聚合对象内封装一个遍历方法,在客户端调用该方法。缺点同样明显,当要改变遍历方式(例如原本是从前往后,改成从后往前),就需要修改聚合类中的遍历方法,违背开闭原则。针对这种场景,结合前两种方式的特点,可以将遍历方法分离出来,但不是在客户端中实现,而是创建一个迭代器类,类中持有聚合对象,并实现迭代方法。这样对客户端不用暴露聚合对象内部,又实现了遍历方法和聚合对象的分离。

本示例展示如何在客户端中通过自定义迭代器遍历自定义聚合类内的元素。客户端声明一个具体聚合类(以抽象聚合接口类型声明),然后初始化该聚合的元素。再通过聚合类的getIterator方法获取具体迭代器类实例(以抽象迭代器类型)。最后调用该Iterator的相关方法完成遍历。

结构

迭代器接口
定义迭代器角色的方法,获取聚合内第一个元素的方法first,获取下一个元素的方法next,判断是否有下一个元素的方法hasNext
具体迭代器类
迭代器接口的实现类。持有聚合元素的集合List<Object>,持有当前处理元素的下表index。实现fistnexthasNext三个接口方法。
抽象聚合接口
定义聚合角色的方法,增加聚合元素的方法add,移除聚合元素的方法remove,获取一个迭代器示例的方法getIterator
具体聚合类
抽象聚合接口的实现类,以List<Object>持有一个聚合示例。实现抽象聚合接口中的addremovegetIterator方法

代码演示

  1. package com.yukiyama.pattern.behavior;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * 迭代器模式
  6. */
  7. public class IteratorDemo {
  8. public static void main(String[] args) {
  9. // 声明一个聚合实例
  10. AbstractAggregation agg = new MyAggregation();
  11. // 通过add方法初始化这个聚合
  12. agg.add("刘备");
  13. agg.add("关羽");
  14. agg.add("张飞");
  15. // 声明一个迭代器实例
  16. Iterator iter = agg.getIterator();
  17. // 取出第一个元素
  18. System.out.println("第一个元素: " + iter.first().toString());
  19. // 调用迭代器的hasNext和next方法迭代遍历,用toString将元素转为String输出
  20. System.out.println("====开始迭代遍历====");
  21. while(iter.hasNext()) {
  22. System.out.println(iter.next().toString());
  23. }
  24. }
  25. }
  26. /**
  27. * 迭代器接口
  28. * 定义迭代器角色的方法,获取聚合内第一个元素的方法first,获取下一个元素
  29. * 的方法next,判断是否有下一个元素的方法hasNext。
  30. */
  31. interface Iterator{
  32. Object first();
  33. Object next();
  34. boolean hasNext();
  35. }
  36. /**
  37. * 具体迭代器实现类
  38. * 迭代器接口的实现类。持有聚合元素的集合List<Object>,并通过有参构造器
  39. * 初始化该集合。持有当前处理元素的下表index,初始值为-1,表示初识时未
  40. * 处理任何元素。实现fist,next和hasNext三个接口方法。
  41. */
  42. class MyIterator implements Iterator{
  43. private List<Object> list;
  44. private int index = -1;
  45. public MyIterator(List<Object> list) {
  46. this.list = list;
  47. }
  48. @Override
  49. public Object first() {
  50. return list.get(0);
  51. }
  52. @Override
  53. public Object next() {
  54. Object obj = null;
  55. // 判断有下一个元素时,获取下一个元素,当前元素下标index+1
  56. if(this.hasNext()) {
  57. obj = list.get(index+1);
  58. index++;
  59. }
  60. return obj;
  61. }
  62. @Override
  63. public boolean hasNext() {
  64. if(index < list.size() - 1) {
  65. return true;
  66. } else {
  67. return false;
  68. }
  69. }
  70. }
  71. /**
  72. * 抽象聚合类接口
  73. * 定义三个聚合角色的方法,增加聚合元素的方法add,移除聚合元素的方法remove,
  74. * 获取一个迭代器实例的方法getIterator。
  75. */
  76. interface AbstractAggregation{
  77. void add(Object obj);
  78. void remove(Object obj);
  79. public Iterator getIterator();
  80. }
  81. /**
  82. * 具体聚合实现类
  83. * 抽象聚合接口的实现类,以List<Object>持有一个聚合示例。实现抽象聚合接口
  84. * 中的add,remove,getIterator方法。其中getIterator获取一个具体迭代器
  85. * 类的实例,获取方式是通过有参构造器new一个具体迭代类的实例并返回,构造器
  86. * 参数是聚合类内部持有的聚合对象List<Object> list。
  87. */
  88. class MyAggregation implements AbstractAggregation{
  89. private List<Object> list = new ArrayList<>();
  90. @Override
  91. public void add(Object obj) {
  92. list.add(obj);
  93. }
  94. @Override
  95. public void remove(Object obj) {
  96. list.remove(obj);
  97. }
  98. @Override
  99. public Iterator getIterator() {
  100. return new MyIterator(list);
  101. }
  102. }