Ruby | Template Method


スポンサーリンク

Template Methodのポイントはこんな感じ。

  • 抽象クラスを定義して、共通する基本的な処理を抽象メソッドとして持たせる
  • それぞれの処理の詳細は具象クラスに持たせる
  • 基本的な考え方は、骨格となるメソッドをもった抽象基底クラスを構築すること。骨格となるメソッドをテンプレートメソッドという
  • 変わらないもの(テンプレートメソッド)と変化するもの(サブクラスで提供される詳細な処理)を分離することが目的

クラス図はこんな感じです。

f:id:sho322:20140823230332j:plain

ここで抽象クラス抽象クラスと言っていますが、Rubyでは抽象クラスも抽象メソッドもサポートしていません。
抽象クラスや抽象メソッドのアイデアは、Rubyが持つ手軽で動的な考え方にそぐわないからです。

そのため、Rubyで擬似的に抽象メソッドを実装する方法として、抽象メソッドを誰かが呼びだそうとした時は例外を投げるという方法を取ります。

サンプルです。

f:id:sho322:20140823230352j:plain

抽象クラスにテンプレートになるメソッドを定義します。
で、実際の処理は具象クラスに書いていくイメージですね。

Report.rb

class Report

  attr_accessor :title
  attr_accessor :text
  def initialize 
    @title = 'my daily'
    @text = ['It\'s sunny day','I\'m fine']
  end


  def output_report
    output_start
    output_head
    output_body_start
    output_body
    output_body_end
    output_end
  end

  def output_body
    @text.each do |line|
      output_line(line)
    end
  end

  def output_start
    raise 'Called abstract method: output_start'
  end

  def output_head
    raise 'Called abstract method: output_head'
  end

  def output_line(line)
  	raise 'Called abstract method: output_line'
  end
  
  def output_body_end
    raise 'Called abstract method: output_body_end'
  end

  def output_end
  	raise 'Called abstract method: output_end'
  end

end

HTMLReport.rb

# coding: utf-8
require './Report.rb'

class HTMLReport < Report
  def output_start
    puts('<html>')
  end

  def output_head
    puts('<head>')
    puts("<title>#{@title}</title>")
    puts('</head>')
  end

  def output_body_start
    puts('<body>')
    puts('<h2>html output start</h2>')
  end

  def output_line(line)
    puts("<p>#{line}</p>")
  end

  def output_body_end
  	puts('</body>')
  end

  def output_end
  	puts('</html>')
  end


end


PlainTextReport.rb

# coding: utf-8

require './Report.rb'
class PlainTextReport < Report

  def output_start
    puts "plain text output start"
  end

  def output_head
    puts("======#{@title}======")
    puts
  end

  def output_body_start

  end


  def output_line(line)
    puts(line)
  end

  def output_body_end
  end

  def output_end

  end
end

それで、これらを使うための記述は簡単にかけます。

action.rb

# coding: utf-8
require './HTMLReport.rb'
require './PlainTextReport.rb'

report = HTMLReport.new
report.output_report

report = PlainTextReport.new
report.output_report

で、結果は以下のように表示されます。
f:id:sho322:20140823230359j:plain

以上、Template Methodでした★