LoginSignup
3
0

この記事は何

デザインパターンについて、Rubyでどのような使い方ができるかをまとめた記事です。
デザインパターン自体の解説は詳しく行いません。

Iteratorパターンとは

Iteratorパターンとは、集合体に対して順番にアクセスするためのインターフェースを提供し、その実装を容易にするデザインパターンです。
詳しくは以下の記事をご覧ください。

Rubyでのコード例

元々のJava等での実装に則って実装すると以下のような形になると思います。
ただ、Rubyではこのような実装を行うことはあまりないと思います。(詳しくは次の項で解説します)

class ItemListIterator
  def initialize(item_list)
    @item_list = item_list
    @current_index = 0
  end
  
  def has_next?
    @current_index < @item_list.length()
  end

  def next
    return nil unless has_next?
    
    item = @item_list.get_at(@current_index)
    @current_index += 1
    return item
  end
end

class ItemList
  def initialize()
    @item_list = []
  end

  def get_at(index)
    @item_list[index]
  end

  def add(item)
    @item_list << item
  end

  def length()
    @item_list.length
  end

  def iterator
    ItemListIterator.new(self)
  end
end

これらのクラスを用いて以下のようにイテレーターを実現できます。

Item = Struct.new(:a, :b)

item_list = ItemList.new()
item_list.add(Item.new(1, 2))
item_list.add(Item.new(2, 3))
item_list.add(Item.new(3, 4))

iterator = item_list.iterator()

while iterator.has_next? do
  puts iterator.next()
end
実行結果
#<struct Item a=1, b=2>
#<struct Item a=2, b=3>
#<struct Item a=3, b=4>

どのような時に使えるか

前項の冒頭でも紹介した通り、RubyではIteratorパターンそのものを実装する機会はほとんどないと思います。

その理由はEnumerableモジュールが提供されているためです。
Enumerableモジュールを利用すると以下のように、簡単にイテレータの実装が可能です。

class ItemList
  include Enumerable

  def initialize()
    @item_list = []
  end

  def add(item)
    @item_list << item
  end

  def each(&block)
    @item_list.each(&block)
  end
end

Item = Struct.new(:a, :b)

item_list = ItemList.new()
item_list.add(Item.new(1, 2))
item_list.add(Item.new(2, 3))
item_list.add(Item.new(3, 4))

item_list.each do |item|
  puts item
end

Enumerableモジュールは以下の記事で詳しく解説されています。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0