引言
在日常开发学习中,熟练的使用设计模式可以极大的提高我们的工作效率。诚然,对于那么多的设计模式,我们往往仅会去深入了解日常被使用最多的设计模式。
当然,也有一些设计模式,随着高级语言的不断扩展,逐渐走向了没落。一如今天所要讨论的迭代器模式,由于容器的大量使用,使得iterator这一设计模式使用度就降低了许多。那我们就具体聊聊关于迭代器的那些事吧!
什么是迭代器模式
设计模式中对迭代器的定义是: Iterator是用来解决对聚合对象的遍历问题,将聚合的遍历封装到一个类中进行,这样就避免了暴露这个聚合对象的内部表示的可能
很官方,但是也是相对的晦涩一点,让我们先看看它的经典UML图,再来开始讨论它:
如前面所述,迭代器主要是去用来遍历一个聚合元素,这个聚合元素就是以某种顺序方式存储了数据。它可以是一个整数数组,以顺序存储的方式保存数据,抑或是其它的简单数据结构。
我们可以通过简单的指针操作得到这个迭代的结果的,但是对于一些复杂数据结构迭代处理起来就会比较麻烦。依定义所说,这会导致对象内部数据表示的暴露。我想读到这里大家一定有如下一些共性问题:
1. 如何我隐藏内部数据表示?
2. 我们是否不管在任何情况下,都需要实现一个迭代器来辅助我们去遍历吗?
3. 如果不是,那又何时才是实现它的好时机呢?
让我们一个一个的来处理这些问题。
首先,我们可以思考如下的一个例子: 程序中有一个对象数组需要被遍历,通常情况下,我想大家都会使用如下的方法:
1 | for (int i = 0; i < n; ++i) {...} |
对于一个数组来说使用如上的方法来说,可以是十分的简单。但若是一个较为复杂的数据结构如: 链表、树、图等,对于它们的迭代遍历,我们可远非如同遍历数组一样的容易了。每次的迭代程序,可能都需要一定的测试保证其正确性后才会投入使用。但若是使用迭代器来说就相对的轻松许多,你无需关心它是如何实现的,在使用上所有的迭代器都是一致的。
实例分析
我们可以使用迭代器完成如下vector容器的遍历
1 |
|
如上所示,十分的容易。除此之外,你还可以将vevtor替换为set、map等数据结构,同样的操作依旧是完全适用的。
这样的表示,将迭代操作交由外部类处理,无需内部提供一个迭代的操作,降低了暴露内部实现的细节。
使用场合
并非所有的情况下,都需要使用迭代器的。毕竟这会增加系统的一个复杂度,因此它的应用场景大致如下所示:
- 访问一个聚合对象的内容,不需要暴露它的内部表示
- 支持聚合对象的多种遍历
- 迭代器模式与集合同时存在
既然已经了解它的设计原理,那就动手实践一下吧!
设计一个迭代器
1 | /** |
总结
迭代器就是对于指针的某些功能的封装,在一般的开发过程中,基本不会需要去实现这样一个迭代器。但是这其中的原理,我们需要去理解,将这些设计的想法应用到我们日常的开发之中。