2つのパターン(テンプレートと戦略)は類似しているようです。テンプレートメソッドには、変更する必要がある処理を駆動する骨格メソッドを持つ抽象基本クラスがあります。この処理は、具象クラスによって提供される抽象メソッドを呼び出すことによって行われます。具体的なクラスを選ぶことで、私たちが望むバリエーションを選択します。テンプレートパターンと戦略パターンの違いは何ですか?
たとえば、私たちはReport
クラスを持ち、HTMLReport
クラスはReportから継承しています。私たちのReport
クラスは次のようになります。
class Report
def initialize
@title = 'Monthly Report'
@text = ['Things are going', 'really really well']
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
def output_start
raise StandardError
end
def output_head
raise 'This needs to be implemented by the concrete class'
end
...
end
と私たちの実際の具体的なクラス:
class HTMLReport < Report
def output_start
puts('<html>')
end
def output_head
puts(' <head>')
...
end
...
end
実際の使用を:
report = HTMLReport.new
report.output_report
重要なのは、抽象クラスがために他のメソッドを呼び出すことですアルゴリズムの変数部分を継承することができます(この場合はRubyの継承を介して継承することができます)。次に実際の実装を行います。
しかし、いくつかの欠点(Russ Olsenによる): - 継承を使用します。実行時の柔軟性を制限します...特定のバージョンのalgoを選択すると、私たちの心を変えるのは難しいです。
したがって、戦略パターン: - 厄介な様々なコードを取り出し、それを独自のクラスで分離します。次に、バリエーションごとに1つのクラスのファミリを作成します。
例:
class Formatter
def output_report(title, text)
raise 'Abstract Method called'
end
end
class HTMLFormatter < Formatter
def output_report(title, text)
puts('<html>')
puts(' <head>')
puts(" <title>#{title}</title>")
puts(' </head>')
...
end
今すぐ私たちのReport
クラスは次のようになります。
class Report
attr_reader :title, :text
attr_accessor :formatter
def initialize(formatter)
@title = 'Monthly Report'
@text = ['Things are going', 'really, really well.']
@formatter = formatter
end
def output_report
@formatter.output_report(@title, @text)
end
end
だから、私が間違っている場合、それは同じインタフェースを持っているすべての戦略以来のように見える私を修正し、我々はReport
クラスでそれらに委託することができます。 Report
クラスは、GOFの人々によってcontext
と呼ばれています。
しかし、これによって実行時に戦略をどのように切り替えることができますか?私たちはまだそれをこのように呼びますか?
report = Report.new(HTMLFormatter.new)
report.output_report
主な違いは何ですか?
テンプレートメソッドバージョンで書式を変更する場合は、別のサブクラスが必要なため、完全に新しいレポートを作成する必要があります。戦略バージョンでは、新しいフォーマッタを既存のレポートに割り当てることができます。 –