人要先认识自己,然后做自己的事,走自己的路。
※引导语问题
集合是编程中最常使用的数据类型之一。尽管如此,集合只是一组对象的容器而已。
大部分集合使用简单列表存储元素。但有些集合还会使用栈、树、图和其他复杂的数据结构。
无论集合的构成方式如何,它都必须提供某种访问元素的方式,便于其他代码使用其中的元素。集合应提供一种能够遍历元素的方式,且保证它不会周而复始地访问同一个元素。
如果你的集合基于列表,那么这项工作听上去仿佛很简单。但如何遍历复杂数据结构(例如树)中的元素呢?例如,今天你需要使用深度优先算法来遍历树结构,明天可能会需要广度优先算法;下周则可能会需要其他方式(比如随机存取树中的元素)。
不断向集合中添加遍历算法会模糊其“高效存储数据”的主要职责。
方案
迭代器模式的主要思想是将集合的遍历行为抽取为单独的迭代器对象。
01迭代器模式是什么定义
迭代器模式,提供一种方法,让你能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历一个容器对象中的各个元素。
迭代器模式是一种行为型设计模式。
[插画]:迭代器是为容器服务的。
02迭代器模式的通用UML类图①迭代器接口:声明了遍历集合所需的操作,获取下一个元素、获取当前位置和重新开始迭代等。
②具体迭代器:实现遍历集合的一种特定算法。迭代器对象必须跟踪自身遍历的进度。这使得多个迭代器可以相互独立的遍历通一集合。
③集合接口:声明一个或多个方法来获取与集合兼容的迭代器。请注意,返回方法的类型必须被声明为迭代器接口,因此具体集合可以返回各种不同种类的迭代器。
④具体集合:会在客户端请求迭代器时返回一个特定的具体迭代器类实体。你可能会琢磨,剩下的集合代码在什么地方呢?不用担心,它也会在同一个类中。只是这些细节对于实际模式来说并不重要,所以我们将其省略了而已。
⑤客户端:通过集合和迭代器的接口与两者进行交互。这样一来客户端无需与具体类进行耦合,允许同一客户端代码使用各种不同的集合和迭代器。
客户端通常不会自行创建迭代器,而是会从集合中获取。但在特定情况下,客户端可以直接创建一个迭代器(例如当客户端需要自定义特殊迭代器时)。
03迭代器模式应用场景●当集合背后为复杂的数据结构,且你希望对客户端隐藏其复杂性时(出于使用便利性或安全性的考虑),可以使用迭代器模式。
●使用该模式可以减少程序中重复的遍历代码。
重要迭代算法的代码往往体积非常庞大。当这些代码被放置在程序业务逻辑中时,它会让原始代码的职责模糊不清,降低其可维护性。
●如果你希望代码能够遍历不同的甚至是无法预知的数据结构,可以使用迭代器模式。
该模式为集合和迭代器提供了一些通用接口。如果你在代码中使用了这些接口,那么将其他实现了这些接口的集合和迭代器传递给它时,它仍将可以正常运行。
04迭代器模式的优缺点优点
●单一职责原则。通过将体积庞大的遍历算法代码抽取为独立的类,你可对客户端代码和集合进行整理。
●开闭原则。你可实现新型的集合和迭代器并将其传递给现有代码,无需修改现有代码。
●你可以并行遍历同一集合,因为每个迭代器对象都包含其自身的遍历状态。
缺点
●如果你的程序只与简单的集合进行交互,应用该模式可能会矫枉过正。
●对于某些特殊集合,使用迭代器可能比直接遍历的效率低。
05迭代器模式在框架中的应用JDK中应用:
java.util.Iterator的所有实现、java.util.Scanner
java.util.Enumeration的所有实现
MyBatis中应用:
DefaultCursor
[识别方法]:迭代器可以通过导航方法(例如next和previous等)来轻松识别。使用迭代器的客户端代码可能没有其所遍历的集合的直接访问权限。