
Итератор на 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