Design Patterns in Ruby: Iterator

A clear example of the Iterator pattern

D. L. Jerome
2 min readJan 18, 2017

The intent

According to the GoF, the intent of the Iterator pattern is to:

“Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.”

The example

The Iterator pattern enables the iteration over objects stored within an aggregate object. The iteration is performed using either an external iterator, an object separate from the aggregate object, or an internal iterator, an iterator defined within the aggregate object itself. Iterators are ubiquitous, and it is helpful to both explore and to understand them.

Some Tidbits

External iterators vs internal iterators

External iterators are client driven, giving you a finer control over the iterations you might wish to perform against an aggregate object. Internal iterators, by contrast, are controlled by the aggregate itself. In such a case, the aggregate is the iterator in the Iterator pattern. The big advantage of internal iterators, however, is the clarity and consistency that they bring to the code.

Put differently, when client code uses an external iterator, it must explicitly call next on the iterator in order to drive it forward. When an internal iterator is given an operation to perform, that operation is applied to every item in the aggregate.

Robust iterators

It can be dangerous to modify an aggregate while it is being traversed, as its possible to end up in a situation where items added to or deleted from the aggregate can muck up the iteration process. Robust iterators are iterators which accommodate insertions and removals without copying the aggregate, which can be overly expensive.

Blocks as iterators

There are many methods within Ruby which use blocks to aid in the application of internal iterators. Common examples of blocks being used as internal iterators in ruby are the each, map, collect, and times methods, which can be called on any instance of the Array class in Ruby.

Enumerable

The Enumerable module in Ruby can be used to more easily add an internal iterator to an aggregate class. Enumerable will give your aggregate class access to the each method, among other helpful collection methods that are commonly used when dealing with arrays and hashes in Ruby.

Going deeper

The Iterator pattern is one of many valuable design patterns. To learn more, check out the seminal work on Design Patterns: The GOF Design Pattern book.

--

--