Vladimir Agafonkin
1/24/2006 6:06:00 PM
Thanks, Robert. You're right, a strategy pattern (I just started
reading "Head First Design Patterns" of O'Reilly). What do you mean by
manually keep references synchronized?
I implented my solution with cross-references, and it seems quite
automated (though there's still room for improvement). Here's what I
came with (in short):
#================================================
class Duck
attr_reader :name
def initialize(name, fly_behaviour=:fly_with_wings,
quack_behaviour=:quack)
@fly_behaviour = FlyBehaviour.new(self, fly_behaviour)
@quack_behaviour = QuackBehaviour.new(self, quack_behaviour)
@name = name
end
def fly
@fly_behaviour.perform
end
def quack
@quack_behaviour.perform
end
end
class Behaviour
def initialize(object, behaviour);
@obj = object;
@behaviour = behaviour;
end
def perform
send(@behaviour)
end
def self.list;
self.protected_instance_methods
end
end
class FlyBehaviour < Behaviour
protected
def fly_with_wings
puts "#{@obj.name} is flying!"
end
def do_not_fly
puts "#{@obj.name} can't fly. :-("
end
end
class QuackBehaviour < Behaviour
protected
def quack
puts "#{@obj.name} is quacking! Quack!!"
end
def squeak
puts "#{@obj.name} is quacking! Squeak!!!"
end
end
class RubberDuck < Duck
def initialize(name)
super(name,:do_not_fly,:squeak)
end
end
ducks = []
ducks << Duck.new("George")
ducks << RubberDuck.new("Wacky")
ducks.each do |duck|
duck.quack
duck.fly
end
p QuackBehaviour.list
#================================================
The next big thing would be to implement generating behaviour-related
methods in the Duck class on the fly. Through method_missing, maybe?
And, of course, behaviour instance variables too. That seems a bit
harder to do, but I'm a programming newbie after all! :-) The perfect
use of the solution would look like:
usually_able_to :fly, :quack, :swim
that looks similiar to Rails has_many and belongs_too. Maybe I need to
check it's code for an idea.
And there's another question: how to make all methods defined in
Behaviour children protected? The code would be more attractive if I
hadn't to write "protected" in the beginning of each behaviour child.