The Template method is build around inheritance, the inheritance has the nature born relationship.
So the Strategy give a delegate solution.
So we use the strategy implementation:
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>') puts(' <body>') text.each do |line| puts(" <p>#{line}</p>" ) end puts(' </body>') puts('</html>') end end class PlainTextFormatter < Formatter def output_report(title, text) puts("***** #{title} *****") text.each do |line| puts(line) end end end
So the Report is much simpler:
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
Usage is as below:
report = Report.new(HTMLFormatter.new) report.output_report
The key idea of Strategy is to define a family of strategy objects those are used by the context class,
its use composition and delegation rather than inheritance, it is easy to switch strategies at runtime
there is a problem about sharing data between context and strategies,
the writer gives a example as below:
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(self) end end
class Formatter def output_report(context) raise 'Abstract method called' end end class HTMLFormatter < Formatter def output_report(context) puts('<html>') puts(' <head>') puts(" <title>#{context.title}</title>") puts(' </head>') puts(' <body>') context.text.each do |line| puts(" <p>#{line}</p>") end puts(' </body>') puts('</html>') end end
This technique simplifies the data flow but increases the coupling.
Then Ruby Duck Typing philosophy shows that we don't need the Formatter class any more.