principlerubyMinor
Is this an appropriate class design for the strategy pattern in Ruby?
Viewed 0 times
thisthedesignrubyappropriateforstrategyclasspattern
Problem
I am fairly satisfied with my solution here but I would definitely appreciate any constructive criticism of my style and design. The basic idea is to use the strategy pattern to simplify assembling a custom procedural generator. I'm using modules rather than classes for improved simplicity of 'mixing' everything together.
Here's the root of the 'strategy' class tree,
One level down, we have another 'parent' pattern which implements a particular strategy 'action' or 'style'. In this case it's an
To see this in action, one strategy module which implements the above contract is `AbstractRoomGener
Here's the root of the 'strategy' class tree,
AbstractStrategy:#
# the contract here is that the child strategy should implement an apply
# function which takes a target problem instance and hash options.
#
module AbstractStrategy
def apply!(problem, opts={})
log.debug "--- AbstractStrategy.apply! problem=#{problem}, opts=#{opts}"
apply(problem, opts)
end
endOne level down, we have another 'parent' pattern which implements a particular strategy 'action' or 'style'. In this case it's an
AbstractGenerationStrategy which implements apply according to the contract above.#
# the contract here is that the child strategy needs to implement "generate_[component]!({})"
#
module AbstractGenerationStrategy extend AbstractStrategy
include AbstractStrategy
def extend!(base)
log.debug("--- extending #{base}")
self.extend(base)
end
#
# => use like -- generate :rooms, ConstructNestedRoomsStrategy, ...opts...
#
def generate(component, strategy, opts={})
log.debug "--- AbstractGenerationStrategy.generate[component=#{component}, strategy=#{strategy}]"
extend!(strategy)
apply!(component,opts)
end
def apply(component_to_generate, opts)
log.debug "--- AbstractGenerationStrategy.apply component=#{component_to_generate}, opts=#{opts})"
self.send("generate_#{component_to_generate}!", opts)
end
endTo see this in action, one strategy module which implements the above contract is `AbstractRoomGener
Solution
Stop trying to write Ruby like Java. You've got a whole mess of modules to do something fairly simple.
Most (not all) of the Gang of Four patterns are workarounds for lack of flexibility in languages like C++ and Java, and are less necessary in a language like Ruby that has classes that are first-class objects and always extensible.
I'd like to know a bit more about your use case, but it seems to me that you can probably remove a layer or two of indirection.
Most (not all) of the Gang of Four patterns are workarounds for lack of flexibility in languages like C++ and Java, and are less necessary in a language like Ruby that has classes that are first-class objects and always extensible.
I'd like to know a bit more about your use case, but it seems to me that you can probably remove a layer or two of indirection.
Context
StackExchange Code Review Q#4930, answer score: 3
Revisions (0)
No revisions yet.