Strategy design pattern with Ruby blocks

My last post was about the strategy pattern. The strategy pattern is a great way to vary part of an algorithm, using composition of objects. Ruby allows for a variation on this technique; the variation is to use block objects.

Why?

Using blocks to vary part of an algorithm is very common in the Ruby community. It can improve the readability of your code and is particularly useful for creating DSLs.

Example

Here is an example Report class. It looks similar to the one in the strategy pattern post but has been modified slightly to accept a block. The output_report method calls the block, passing in self to provide context.

class Report
  attr_reader :title, :text

  def initialize(&formatter)
    @title = 'Acme Inc Report'
    @text = ['Good stuff', 'What an awesome quater']
    @formatter = formatter
  end

  def output_report
    @formatter.call(self)
  end
end

Now we can initialize Report with a block. The block provides the part of the algorithm that we want to vary.

report = Report.new do |context|
  puts context.title
  context.text.each do |line|
    puts line
  end
end

Finally, we can check the output.

report.output_report
#=> Acme Inc Report
#=> Good stuff
#=> What an awesome quater

Conclusion

Implementing the strategy pattern using blocks is more idiomatic Ruby. It can make your code more readable and is great for implementing DSLs.