Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git на GitByBit.com! Привет! Хочешь круто подтянуть Git? Глянь мой новый курс на GitByBit.com!
Итератор

Итератор на Ruby

Итератор — это поведенческий паттерн, позволяющий последовательно обходить сложную коллекцию, без раскрытия деталей её реализации.

Благодаря Итератору, клиент может обходить разные коллекции одним и тем же способом, используя единый интерфейс итераторов.

Сложность:

Популярность:

Применимость: Паттерн можно часто встретить в Ruby-коде, особенно в программах, работающих с разными типами коллекций, и где требуется обход разных сущностей.

Признаки применения паттерна: Итератор легко определить по методам навигации (например, получения следующего/предыдущего элемента и т. д.). Код использующий итератор зачастую вообще не имеет ссылок на коллекцию, с которой работает итератор. Итератор либо принимает коллекцию в параметрах конструктора при создании, либо возвращается самой коллекцией.

Концептуальный пример

Этот пример показывает структуру паттерна Итератор, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.

main.rb: Пример структуры паттерна

class AlphabeticalOrderIterator
  # Примесь Enumerable в Ruby предоставляет классы методами обхода, поиска и
  # сортировки значений. Класс, реализующий Enumerable должен определить метод
  # `each`, который возвращает (в yield) последовательно элементы коллекции.
  include Enumerable

  # Этот атрибут указывает направление обхода.
  # @return [Boolean]
  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

  # Метод iterator возвращает объект итератора, по умолчанию мы возвращаем
  # итератор с сортировкой по возрастанию.
  #
  # @return [AlphabeticalOrderIterator]
  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

# Клиентский код может знать или не знать о Конкретном Итераторе или классах
# Коллекций, в зависимости от уровня косвенности, который вы хотите сохранить в
# своей программе.
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: Результат выполнения

Straight traversal:
First
Second
Third

Reverse traversal:
Third
Second
First

Итератор на других языках программирования

Итератор на C# Итератор на C++ Итератор на Go Итератор на Java Итератор на PHP Итератор на Python Итератор на Rust Итератор на Swift Итератор на TypeScript