REBAJA de primavera
Iterator

Iterator en Ruby

Iterator es un patrón de diseño de comportamiento que permite el recorrido secuencial por una estructura de datos compleja sin exponer sus detalles internos.

Gracias al patrón Iterator, los clientes pueden recorrer elementos de colecciones diferentes de un modo similar, utilizando una única interfaz iteradora.

Complejidad:

Popularidad:

Ejemplos de uso: El patrón es muy común en el código Ruby. Muchos frameworks y bibliotecas lo utilizan para proporcionar una forma estandarizada de recorrer sus colecciones.

Identificación: El patrón Iterator es fácil de reconocer por sus métodos de navegación (como next, previous y otros). El código cliente que utiliza iteradores puede no tener acceso directo a la colección recorrida.

Ejemplo conceptual

Este ejemplo ilustra la estructura del patrón de diseño Iterator. Se centra en responder las siguientes preguntas:

  • ¿De qué clases se compone?
  • ¿Qué papeles juegan esas clases?
  • ¿De qué forma se relacionan los elementos del patrón?

main.rb: Ejemplo conceptual

class AlphabeticalOrderIterator
  # In Ruby, the Enumerable mixin provides classes with several traversal and
  # searching methods, and with the ability to sort. The class must provide a
  # method each, which yields successive members of the collection.
  include Enumerable

  # This attribute indicates the traversal direction.
  attr_accessor :reverse
  private :reverse

  # @return [Array]
  attr_accessor :collection
  private :collection

  # @param [Array] collection
  # @param [Boolean] reverse
  def initialize(collection, reverse: false)
    @collection = collection
    @reverse = reverse
  end

  def each(&block)
    return @collection.reverse.each(&block) if reverse

    @collection.each(&block)
  end
end

class WordsCollection
  # @return [Array]
  attr_accessor :collection
  private :collection

  def initialize(collection = [])
    @collection = collection
  end

  # The `iterator` method returns the iterator object itself, by default we
  # return the iterator in ascending order.
  def iterator
    AlphabeticalOrderIterator.new(@collection)
  end

  # @return [AlphabeticalOrderIterator]
  def reverse_iterator
    AlphabeticalOrderIterator.new(@collection, reverse: true)
  end

  # @param [String] item
  def add_item(item)
    @collection << item
  end
end

# The client code may or may not know about the Concrete Iterator or Collection
# classes, depending on the level of indirection you want to keep in your
# program.
collection = WordsCollection.new
collection.add_item('First')
collection.add_item('Second')
collection.add_item('Third')

puts 'Straight traversal:'
collection.iterator.each { |item| puts item }
puts "\n"

puts 'Reverse traversal:'
collection.reverse_iterator.each { |item| puts item }

output.txt: Resultado de la ejecución

Straight traversal:
First
Second
Third

Reverse traversal:
Third
Second
First

Iterator en otros lenguajes

Iterator en C# Iterator en C++ Iterator en Go Iterator en Java Iterator en PHP Iterator en Python Iterator en Rust Iterator en Swift Iterator en TypeScript