Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Ruby | Iterator Pattern

概要

Iterator Pattern

詳細

Iterator Patternは、内部オブジェクトの保持形式に依存せずに外部に連続して走査するための
インターフェースを提供するパターンです。

サンプル1仕様

Stringクラスの各単語へのIteratorを実装する。
ここでは、半角スペースで区切られた文字を単語とします。

サンプル1

class String
  def each_word
    split(' ').each do |v|
      yield v
    end
  end
end

"hoge hoge".each_word do |v|
  print v + ":"
end

出力

hoge:hoge:

サンプル2仕様

自作の集約クラスにEnumerableの機能を追加します。
eachを実装して、Iteratorの機能を実装するとともに
Enumerableの様々なメソッドが利用できるようになります。

サンプル2

require 'tbpgr_utils'
require 'attributes_initializable'
require 'pp'

class Person
  include AttributesInitializable
  attr_accessor_init :name, :age

  def <=>(other)
    name <=> other.name
  end
end

class Persons
  include Enumerable
  attr_reader :persons
  def initialize(persons)
    @persons = persons
  end

  def each
    @persons.each { |v|yield v }
  end

  def <<(person)
    @persons << person
  end
end

tmp_persons = []
[
  {name: "tanaka", age: 34},
  {name: "sato", age: 44},
].each do |person|
  tmp_persons << Person.new(person)
end

persons = Persons.new tmp_persons
persons.each { |person|pp person }
print persons.map { |person|Person.new({name: person.name.capitalize, age: (person.age + 1)}) }
puts
print persons.reduce(0) { |ret, person|ret += person.age;ret }
puts
print persons.sort
persons << Person.new({name: "suzuki", age:99})
puts
print persons.reduce(0) { |ret, person|ret += person.age;ret }

__END__
AttributesInitializableは tbpgr_utils gemの機能です。
AttributesInitializableのincludeとattr_accessor_initで
attr_accessorの宣言とコンストラクタでのメンバへの変数設定を一気にやっていると思ってください。

tbpgr_utils gemについては下記参照
https://github.com/tbpgr/tbpgr_utils

出力

#<Person:0x2dfc138 @age=34, @name="tanaka">
#<Person:0x2dfc0c0 @age=44, @name="sato">
[#<Person:0x2e066e0 @name="Tanaka", @age=35>, #<Person:0x2e06638 @name="Sato", @age=45>]
78
[#<Person:0x2dfc0c0 @name="sato", @age=44>, #<Person:0x2dfc138 @name="tanaka", @age=34>]
177