
Iterator を Ruby で
Iterator は、 振る舞いに関するデザインパターンの一つで、 複雑なデータ構造の内部の詳細を公開することなく、 順次横断的に探索することを可能とします。
Iterator のおかげで、 クライアントは、 異なるコレクション上の要素の探索を、 単一のイテレーター・インターフェースを使用して同様の方法で行えます。
複雑度:
人気度:
使用例: このパターンは、 Ruby コードではよく見かけます。 多くのフレームワークやライブラリーがこれを使用してコレクション上の探索の標準的方法を提供します。
見つけ方: Iterator は、 next
や previous
などの操舵用メソッドの存在から簡単に識別できます。 イテレーターを使ったクライアント・コードには、 探索対象のコレクションへの直接のアクセスがないかもしれません。
概念的な例
この例は、 Iterator デザインパターンの構造を説明するためのものです。 以下の質問に答えることを目的としています:
- どういうクラスからできているか?
- それぞれのクラスの役割は?
- パターンの要素同士はどう関係しているのか?
main.rb: 概念的な例
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: 実行結果
Straight traversal: First Second Third Reverse traversal: Third Second First