Pull algorithm out into it's own object. Basically you send in the object and delegate to it using duck-typing.
The key idea of the Strategy Pattern is to define a family of objects (the strategies), which all do the same thing (implement the same methods). Given that all of the strategy objects look the same from the outside, the context can treat the strategies like interchangable parts.
In Ruby, can be nice to implement the different strategies
as proc
objects (nice for one liners).
When to use: Supply the context with an object which knows how to perform some variation of a task.
# proc based Strategy pattern
class Report
attr_reader :formatter
def initialize(&formatter)
@formatter = formatter #capture the block as a proc
end
def output_report
formatter.call(self)
end
end
HTML_FORMATTER = lambda do |context|
puts '<html>'
puts 'other stuff'
puts context.title
puts context.text.each do |line|
puts line
end
puts 'final things'
end
# and then run it with
Report.new(&HTML_FORMATTER)
report.output_report
Another nice way, which I think is Strategy patternesque mentioned in the Eloquent Ruby book was to use modules and interchange dynamically... e.g.
module FancyWriter
class Setup
def something
# do something
end
end
class Performer
def some_other_method
# ommitted for .. fun
end
end
end
module LessFancyWriter
class Setup
def something
# do something
end
end
class Performer
def some_other_method
# ommitted for .. fun
end
end
end
#now we can just interchange the two at runtime
if something_is_fancy?
writer = FancyWriter
else
writer = LessFancyWriter
end
# ok, or...
writer = something_is_fancy? ? FancyWriter : LessFancyWriter
# whatever, purists
#then we just call as normalish
writer::Setup
writer::Performer
# ok, so not the nicest class names, but naming is hard, naming is hard.
Page created on 6 Jun 2020