定义

提供一种方法顺序访问一个聚合对象中的各个元素,而又不需暴露对象的内部表示。

结构和说明

行为型模式-迭代器模式 - 图1

示例代码

  1. public class IteratorDemo {
  2. /**
  3. * 迭代器接口,定义访问和遍历元素的操作
  4. */
  5. public static interface Iterator {
  6. /**
  7. * 移动到聚合对象的第一个位置
  8. */
  9. void first();
  10. /**
  11. * 移动到聚合对象的下一个位置
  12. */
  13. void next();
  14. /**
  15. * 判断是否已经移动到聚合对象的最后一个位置
  16. *
  17. * @return true 表示已经移动到聚合对象的最后一个位置; false 反之
  18. */
  19. boolean isDone();
  20. /**
  21. * 获取迭代的当前元素
  22. *
  23. * @return 迭代的当前元素
  24. */
  25. Object currentItem();
  26. }
  27. /**
  28. * 具体的迭代器实现对象,示意的是聚合对象为数组的迭代器
  29. * 不同的聚合对象相应的迭代器实现是不一样的
  30. */
  31. public static class ConcreteIterator implements Iterator {
  32. /**
  33. * 持有被迭代的具体的聚合对象
  34. */
  35. private ConcreteAggregate aggregate;
  36. /**
  37. * 内部索引,记录当前迭代到的索引位置
  38. * -1表示刚开始的时候,迭代器指向聚合对象第一个对象之前
  39. */
  40. private int index = -1;
  41. /**
  42. * 构造方法,传入被迭代的具体的聚合对象
  43. *
  44. * @param aggregate 被迭代的具体的聚合对象
  45. */
  46. public ConcreteIterator(ConcreteAggregate aggregate) {
  47. this.aggregate = aggregate;
  48. }
  49. @Override
  50. public void first() {
  51. index = 0;
  52. }
  53. @Override
  54. public void next() {
  55. if (index < aggregate.size()) {
  56. index = index + 1;
  57. }
  58. }
  59. @Override
  60. public boolean isDone() {
  61. return index >= aggregate.size();
  62. }
  63. @Override
  64. public Object currentItem() {
  65. return aggregate.get(index);
  66. }
  67. }
  68. /**
  69. * 聚合对象的接口,定义创建相应迭代器对象的接口
  70. */
  71. public static abstract class Aggregate {
  72. /**
  73. * 工厂方法,创建相应迭代器对象的接口
  74. *
  75. * @return 相应迭代器对象的接口
  76. */
  77. public abstract Iterator createIterator();
  78. }
  79. /**
  80. * 具体的聚合对象,实现创建相应迭代器对象的功能
  81. */
  82. public static class ConcreteAggregate extends Aggregate {
  83. /**
  84. * 示意,表示聚合对象具体的内容
  85. */
  86. private String[] ss = null;
  87. /**
  88. * 构造方法,传入聚合对象具体的内容
  89. *
  90. * @param ss 聚合对象具体的内容
  91. */
  92. public ConcreteAggregate(String[] ss) {
  93. this.ss = ss;
  94. }
  95. @Override
  96. public Iterator createIterator() {
  97. return new ConcreteIterator(this);
  98. }
  99. /**
  100. * 获取索引所对应的元素
  101. *
  102. * @param index 索引
  103. * @return 索引对应的元素
  104. */
  105. public Object get(int index) {
  106. if (index >= ss.length) {
  107. return null;
  108. }
  109. return ss[index];
  110. }
  111. /**
  112. * 获取聚合对象大小
  113. *
  114. * @return 聚合对象的大小
  115. */
  116. public int size() {
  117. return ss.length;
  118. }
  119. }
  120. public static class Client {
  121. public static void main(String[] args) {
  122. Aggregate aggregate = new ConcreteAggregate(new String[]{"张三", "李四", "王二", "麻子"});
  123. Iterator iterator = aggregate.createIterator();
  124. // 首先设置迭代器到第一个元素
  125. iterator.first();
  126. while (!iterator.isDone()) {
  127. Object currentItem = iterator.currentItem();
  128. System.out.println("currentItem = " + currentItem);
  129. iterator.next();
  130. }
  131. }
  132. }
  133. }

调用顺序

优缺点

优点

  • 更好的封装性
  • 迭代器模式可以让你访问一个聚合对象的内容,而无须暴露该聚合对象的内部表示,从而提高聚合对象的封装性
  • 可以以不同的遍历方式来遍历一个聚合
  • 使用迭代器模式,是的聚合对象的内容和具体的迭代算法分离。这样可以通过使用不同的迭代器实例、不同的遍历方式来遍历一个聚合对象了。
  • 迭代器简化了聚合接口。
  • 有了迭代器接口,则聚合本身就不需要再定义这些接口了,从而简化了聚合的接口定义。
  • 简化客户端调用
  • 迭代器为遍历不同的聚合对象提供了一个统一的接口,使得客户端遍历聚合对象的内容变得更简单。
  • 同一个聚合可以有多个遍历
  • 每个迭代器保持它自己的遍历状态,比如前面实现中的迭代索引位置,因此可以对同一个聚合对象同时进行多个遍历。

思考

本质

控制访问聚合对象中的元素。

何时选用

  • 如果你希望提供一个聚合对象的内容,但是又不想暴露它的内部表示的时候,可以使用迭代器模式来提供迭代器接口,从而让客户端只是通过迭代器接口来访问聚合对象,而无须关心聚合对象的内部实现。
  • 如果你希望有多种遍历方式可以访问聚合对象,可以使用迭代器模式。
  • 如果你希望为遍历不同的聚合对象提供一个统一的接口,可以使用迭代器模式。

相关模式

  • 迭代器模式和组合模式

这两个模式可以组合使用。
组合模式是一种递归的对象结构,在枚举某个组合对象的子对象的时候,通常会使用迭代器模式。

  • 迭代器模式和工厂方法模式

这两个模式可以组合使用。
在聚合对象创建迭代器的时候,通常会采用工厂方法模式来实例化相应的迭代器对象。