Imagine you're exploring a treasure chest filled with various gems, and you want a systematic way to check each gem without getting lost in the treasure trove. The Iterator Design Pattern is like a guide, helping you traverse through different collections without worrying about the underlying structure. It's a behavioral pattern that provides a uniform interface for accessing elements of a collection, without exposing its internal details.

Concept:

  • Iterator: Represents an interface for iterating over elements in a collection.
  • ConcreteIterator: Implements the Iterator interface and keeps track of the current position in the traversal.
  • Aggregate: Represents an interface for creating an Iterator.
  • ConcreteAggregate: Implements the Aggregate interface to create an Iterator specific to its collection.
  • Client: Initiates the iteration.

Example:

Let's put on our explorer hats and navigate through a collection of gems using the Iterator Pattern.

Iterator Interface:

# Iterator Interface
class GemIterator
  def has_next?
    raise NotImplementedError, 'Subclasses must implement the has_next? method'
  end

  def next_gem
    raise NotImplementedError, 'Subclasses must implement the next_gem method'
  end
end

ConcreteIterator:

# ConcreteIterator
class TreasureChestIterator < GemIterator
  def initialize(treasure_chest)
    @treasure_chest = treasure_chest
    @index = 0
  end

  def has_next?
    @index < @treasure_chest.size
  end

  def next_gem
    gem = @treasure_chest[@index]
    @index += 1
    gem
  end
end

Aggregate Interface:

# Aggregate Interface
class GemCollection
  def create_iterator
    raise NotImplementedError, 'Subclasses must implement the create_iterator method'
  end
end

ConcreteAggregate:

# ConcreteAggregate
class TreasureChest < GemCollection
  def initialize
    @gems = ['Ruby', 'Sapphire', 'Emerald', 'Diamond', 'Topaz']
  end

  def create_iterator
    TreasureChestIterator.new(self)
  end

  def size
    @gems.size
  end

  def [](index)
    @gems[index]
  end
end

Explorer Code:

# Explorer code using the Iterator Pattern
treasure_chest = TreasureChest.new
iterator = treasure_chest.create_iterator

puts 'Exploring the treasure chest:'
while iterator.has_next?
  gem = iterator.next_gem
  puts "Found gem: #{gem}"
end

In this treasure-filled example:

  • GemIterator is the iterator interface with methods like has_next? and next_gem.
  • TreasureChestIterator is the concrete iterator that traverses the gems in a treasure chest.
  • GemCollection is the aggregate interface providing the create_iterator method.
  • TreasureChest is the concrete aggregate representing a collection of gems with a specific iterator.
  • The explorer code sets up a treasure chest and uses an iterator to navigate through its gems.

This pattern simplifies the traversal of collections and shields the explorer (client code) from the complexities of different collection structures. So, go ahead, explore the gems, and let the iterator guide your journey!