Design Patterns in Ruby: Chain of Command
Chain of Responsibility:
bq. Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
p>. “GOF”:http://www.amazon.com/gp/product/0201633612/ p.223
In the book, the GoF mention how in Smalltalk it is possible to do a very different implementation using the @doesNotUnderstand@ mechanism. Ruby of course has a similar one in @method_missing@, so I thought that I would use this in an implementation example of Chain of Responsibility. There is also an alternative implementation beneath it that does not use @method_missing@.
# Generic implementation for Chain of Responsibility
module Chainable
def next_in_chain(link)
@next = link
end
def method_missing(method, *args, &block)
if @next == nil
puts “huh?”
return
end
@next.__send__(method, *args, &block)
end
end
class X
include Chainable
def initialize(link)
next_in_chain(link)
end
def do_x
puts “x”
end
end
class Y
include Chainable
def do_y
puts “y”
end
end
y1 = Y.new
x1 = X.new(y1)
x1.do_x
x1.do_y
x1.do_z
Now, I guess it might not be a good idea to define method_missing in a module (comment anyone?), so you could of course change it to let the classes handle that themselves. I also did this alternative implementation that does not use method_missing but is still fairly generic.
# Alternative implementation for Chain of Responsibility
module Chainable
def next_in_chain
nil
end
def handle_message(message, *args, &block)
if self.respond_to?(message)
self.__send__(message, *args, &block)
else
next_in_chain.handle_message(message, *args, &block) unless next_in_chain.nil?
end
end
end
class X
include Chainable
def initialize(link)
@next = link
end
def next_in_chain
@next
end
def do_x(x)
puts x
end
end
class Y
include Chainable
def do_y
yield ‘y’
end
end
y1 = Y.new
x1 = X.new(y1)
x1.handle_message(:do_x, ‘x’)
x1.handle_message(:do_y) {|y| puts y}
x1.handle_message(:do_z)
Trackbacks
Trackbacks are closed.

