The Command Pattern
The chapter in PPP that discusses the command design pattern opens with a cartoon of a general putting his finger in the eye of what seems to be a junior enlisted troop. So that got me pretty confident I would understand the command pattern pretty easily seeing as I’ve been junior enlisted and I’ve had officers actually put there fingers in my eye… err, a knifehand probably, and it was rare that an officer did knifehanded me, more likely it was another enlisted Marine, like a squad leader.
The Command design pattern intends to separate and decouple both temporally (timing of calls to validation or execution) and physically (entirely different classes) an object of invocation from the object that receives the message of invocation.
The following ruby code demonstrates such a set-up, using Marines as an example…
class Marine
attr_reader :action
def initialize(action)
@action = action
end
def name
self.class
end
end
class SquadLeader < Marine
attr_reader :route, :mission
def initialize(route, mission)
super 'Marines, Condition 1!'
@route = route
@mission = mission
end
def execute
file = File.open route, 'w'
file.write "#{name}: #{mission}\n"
file.close
end
end
class Rifleman < Marine
attr_reader :route, :mission
def initialize(route, mission)
super 'Pew, Pew, Pew!!!'
@route = route
@mission = mission
end
def execute
file = File.open route, 'a'
file.write "#{name}: #{mission}\n"
file.close
end
end
class PlatoonSergeant < Marine
attr_reader :route, :target
def initialize(route, target)
super "Alpha1Actual, we are moving the platoon from #{prettify route} to #{prettify target}..."
@route = route
@target = target
end
def execute
FileUtils.mv route, target
file = File.open target, 'a'
file.write "#{name}: We moved from #{prettify route} to #{prettify target}..."
file.close
end
def prettify(routename)
(routename.chomp File.extname(routename)).capitalize
end
end
# the following class keeps track of the various Marines commands...
class CompositeCommand < Marine
attr_accessor :commands
def initialize
@commands = []
end
def add_command(*args)
args.each { |arg| commands << arg }
end
def execute
commands.each { |command| command.execute }
end
end
Try putting this code into a file named platoon.rb (or your own example) and running through the steps you’ll find in the blog this code was based on: (this design pattern blog by Doug Yun.