This post is part of a series of reviews on the book Design Patterns in Ruby. Check out the Introduction post for a full table of contents along with some generic principles regarding Design Patterns.

Although useful, the template method has some drawbacks of which include, mostly, inheritance. After creating a specific class to execute the algorithm you can’t change your mind due to the binding created by inheritance.

Let’s take a look at how it’d look like if we used object composition to vary algorithms.

Following the same example used in the template method post (reports with different formats), let’s extract the formatting code into its own class an hold a reference to this class on the Report class:

class Report
	attr_reader :title
	attr_accessor :formatter
	
	def initialize(formatter)
		@title = 'My Report'
		@formatter = formatter
	end
	
	def generate_report
		@formatter.generate_report(@title)
	end
end

Now the generic format class and 2 different formatters:

class Formatter
	def generate_report(title)
	end
end

class HTMLFormatter < Formatter
	def generate_report(title)
		puts "<html><body><h1>Header</h1>"
		puts "<p>#{title}</p>"
		puts "<div class='footer'>Footer</div></body></html>"
	end
end

class PlainTextFormatter < Formatter
	def generate_report(title)
		puts "Header\n\n"
		puts "#{title}\n\n"
		puts "Footer"
	end
end

The following example code shows how we can change formatters at runtime with no difficulty:

report = Report.new(HTMLFormatter.new)
report.generate_report
report.formatter = PlainTextFormatter.new
report.generate_report

Ruby offers a different way for us to create strategies due to its support to code blocks (lambdas, procs). Using this different technique we can quickly create our strategies without having to create classes for them:

class Report
	attr_reader :title
	attr_accessor :formatter
	
	def initialize(&formatter)
		@title = 'My Report'
		@formatter = formatter
	end
	
	def generate_report
		@formatter.call(self)
	end
end

Notice we’re passing self as a parameter to the block call so we can access the report object inside the block. Suppose we wanted a quick XML strategy:

report = Report.new do |context|
	puts "<xml><header>Header</header>"
	puts "<body>#{context.title}</body>"
	puts "<footer>Footer</footer></xml>"
end
report.generate_report

Using code blocks to create strategy can be a powerful tool when you need something simple, but more complex strategies should be coded with good old classes for the sake of organization.