Strategy Pattern¶
The strategy pattern (a.k.a policy pattern) allows selecting an algorithm at runtime. This is achieved by creating a family of objects that implement the same interface so client code can select which one of those objects (which strategy/algorithm) to use at runtime.
The user of the strategy is called the context and the algorithms are the strategies.
The strategy pattern is based on composition and delegation (not on class inheritance).
Use Cases¶
Report Generator¶
The context here is Report
, and the strategies are PlainTextFormatter
and HTMLFormatter
. Report
doesn’t know about the details of each report format. It just knows it can call output_format
from the strategy @formatter
and be done with it.
Ruby¶
formatter.rb:
##
# A base abstract class.
#
class Formatter
##
# This method should be implemented by subclasses.
#
def output_report(_title, _text)
raise 'Implement `output_report` in `Formatter` subclasses.'
end
end
plain_text_formatter.rb:
require_relative 'formatter'
##
# Formats the report in Plain Text.
#
class PlainTextFormatter < Formatter
def output_report(title, text)
puts("===== #{title} =====")
text.each do |line|
puts(line)
end
end
end
html_formatter.rb:
require_relative 'formatter'
##
# Formats the report in HTML.
#
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
report.rb:
##
# A reporter class that delegates reporting to instances of subclasses
# of `Formatter`.
#
class Report
attr_reader :title, :text
attr_accessor :formatter
##
# We need an instance of `Formatter` here.
#
def initialize(formatter)
@formatter = formatter
@title = 'Nostromo Final Report'
@text = [
'This is Ripley, last survivor of the Nostromo.',
'Signing off.'
]
end
##
# `output_report` is implemented in subclass of `Formatter`.
#
def output_report
@formatter.output_report(@title, @text)
end
end
Calculating Taxes¶
A tax calculator may choose different algorithms depending on the state or other attribute.