読者です 読者をやめる 読者になる 読者になる

Yamakichi’s blog

yamakichiの技術ブログ

TemplateMethod パターン Ruby

Ruby 思考の整理 開発

TemplateMethodパターン

テンプレートメソッドパターンとは

抽象的な処理と具体的な処理を分離することで、 変化に強い構造を実現する。

2つのオブジェクトによって構成される。

  • 骨格としての「抽象的なベースクラス」
  • 実際の処理を行う「サブクラス」

用いるメリット

  • 抽象的なベースクラス側に、「変わらない基本的なアルゴリズム」を置ける
  • 抽象的なベースクラスは「高レベルの処理」を制御することに集中出来る
  • サブクラス側に、「変化するロジック」を置ける
  • サブクラスは「詳細を埋めること」に集中出来る

f:id:Yamakichi:20161119155738p:plain

実装

  • Report(抽象的なベースのクラス): レポートを出力する
  • HTMLReport(サブクラス): HTMLフォーマットでレポートを出力
  • PlaneTextReport(サブクラス): PlanTextフォーマットでレポートを出力
ベースとなるクラス
class Report
  def initialize
    @title = "html report title"
    @text = ["report line 1", "report line 2", "report line 3"]
  end

  # レポートの出力手順を規定
  def output_report
    output_start
    output_body
    output_end
  end

  # レポートの先頭に出力
  def output_start
    raise NotImplementedError
  end

  # レポートの本文の管理
  def output_body
    @text.each do |line|
      output_line(line)
    end
  end
具体的な処理を実装したサブクラス
HTMLReport
class HTMLReport < Report
  # レポートの先頭に出力
  def output_start
    puts "<html><head><title>#{@title}</title></head><body>"
  end

  # 本文内のLINE出力部分
  def output_line(line)
    puts "<p>#{line}</p>"
  end

  # レポートの末尾に出力
  def output_end
    puts '</body></html>'
  end
end
PlaneTextReport
class PlaneTextReport < Report
  # レポートの先頭に出力
  def output_start
    puts "**** #{@title} ****"
  end

  # 本文内のLINE出力部分
  def output_line(line)
    puts line
  end
end
実行
html_report = HTMLReport.new
html_report.output_report
#<html><head><title>html report title</title></head><body>
#<p>report line 1</p>
#<p>report line 2</p>
#<p>report line 3</p>
#</body></html>

plane_text_report = PlaneTextReport.new
plane_text_report.output_report
#**** html report title ****
#report line 1
#report line 2
#report line 3
変わるもの(具象サブクラス)と変わらないもの(テンプレート)を分離して、変化に強い構造へ。

具象クラスによってオーバーライド出来る(不要ならしなくてもよい)メソッドのことを、 フックメソッドと呼ぶ

凡化 = 抽象化

特化 = 具象化

Special Thanks