概要
Strategy Pattern
詳細
Strategy Patternは、委譲を利用してプログラム内のアルゴリズムの一部を交換可能にします。
サンプル仕様
株式会社HogeHogeの社内レポートを作成する。
レポートはHTMLとMarkdownの2種類です。
(HTMLはMarkdownから出せばいいような気もしますが気にしない。)
・Strategy適用その1(クラスによる抽出)
Strategyパターンを適用するために、文書のフォーマットに関わる処理をクラスに抽出します。
フォーマットごとに別のクラスを作成し、同じ振る舞いを持たせます。
これにより、レポートの抽出処理・フォーマット処理を別々のクラスに責務分割でき、
さらにフォーマットの種類が増えてもフォーマットクラスを増やすことで簡単に拡張できます。
・Strategy適用その2(Procによる抽出)
クラスを定義する代わりにProcを渡します。
クラスによる抽出との使い分けについては、各クラスのメソッドが一つで済むようなシンプルなケースで有効になります。
サンプル修正前
require 'test_toolbox' module HogeHogeInc HTML_FORMATTER = proc do |title, contents| <<-EOS <html> <head> <title>#{title}</title> </head> <body> #{contents} </body> </html> EOS end MARKDOWN_FORMATTER = proc do |title, contents| <<-EOS # #{@title} ## Report #{@contents} EOS end class Report attr_reader :formatter, :title, :contents def initialize(title, contents, formatter) @formatter,@title, @contents = formatter, title, contents end def output_report @formatter.call(@title, @contents) end end end html_report = HogeHogeInc::Report.new("html title", "html contents", HogeHogeInc::HTML_FORMATTER) puts html_report.output_report dp_line __LINE__ markdown_report = HogeHogeInc::Report.new("markdown title", "markdown contents", HogeHogeInc::MARKDOWN_FORMATTER) puts markdown_report.output_report __END__ dp_line は tbpgr_utils gem の機能 詳しくは https://github.com/tbpgr/tbpgr_utils を参照。
出力
<html> <head> <title>html title</title> </head> <body> html contents </body> </html> --------------------|filename=|line=40|-------------------- # ## Report
サンプルパターン適用その1
require 'test_toolbox' module HogeHogeInc class HtmlFormatter def initialize(title, contents) @title, @contents = title, contents end def output_report <<-EOS <html> <head> <title>#{@title}</title> </head> <body> #{@contents} </body> </html> EOS end end class MarkdownFormatter def initialize(title, contents) @title, @contents = title, contents end def output_report <<-EOS # #{@title} ## Report #{@contents} EOS end end class Report attr_reader :formatter def initialize(formatter) @formatter = formatter end def output_report @formatter.output_report end end end html_report = HogeHogeInc::Report.new(HogeHogeInc::HtmlFormatter.new("html title", "html contents")) puts html_report.output_report dp_line __LINE__ markdown_report = HogeHogeInc::Report.new(HogeHogeInc::MarkdownFormatter.new("markdown title", "markdown contents")) puts markdown_report.output_report __END__ dp_line は tbpgr_utils gem の機能 詳しくは https://github.com/tbpgr/tbpgr_utils を参照。
出力
<html> <head> <title>html title</title> </head> <body> html contents </body> </html> --------------------|filename=|line=53|-------------------- # markdown title ## Report markdown contents
サンプルパターン適用その2
require 'test_toolbox' module HogeHogeInc HTML_FORMATTER = proc do |title, contents| <<-EOS <html> <head> <title>#{title}</title> </head> <body> #{contents} </body> </html> EOS end MARKDOWN_FORMATTER = proc do |title, contents| <<-EOS # #{title} ## Report #{contents} EOS end class Report attr_reader :formatter, :title, :contents def initialize(title, contents, formatter) @formatter,@title, @contents = formatter, title, contents end def output_report @formatter.call(@title, @contents) end end end html_report = HogeHogeInc::Report.new("html title", "html contents", HogeHogeInc::HTML_FORMATTER) puts html_report.output_report dp_line __LINE__ markdown_report = HogeHogeInc::Report.new("markdown title", "markdown contents", HogeHogeInc::MARKDOWN_FORMATTER) puts markdown_report.output_report __END__ dp_line は tbpgr_utils gem の機能 詳しくは https://github.com/tbpgr/tbpgr_utils を参照。
出力
<html> <head> <title>html title</title> </head> <body> html contents </body> </html> --------------------|filename=|line=40|-------------------- # markdown title ## Report markdown contents