I have been reading "Head First Design Patterns" [1], which used Java to construct all examples. It's made me wonder what would it take to implement same pattern in Ruby. What would be the different, specially Ruby is not "type" language at all.
The first pattern that I am going to try is "Strategy" pattern. The principal behind "Strategy" pattern is "Favor composition over inheritance". It's interesting to see that at least two different way we can implement this principal in Ruby. One using module, another using class.
Let use the same design in the book, the duck design. Since all duck would have name, and can swim. The Duck base class would contain attribute name and method swim(). All duck swim, you know.
Let use the same design in the book, the duck design. Since all duck would have name, and can swim. The Duck base class would contain attribute name and method swim(). All duck swim, you know.
class Duck attr_reader :name def initialize @name = "simple duck" end def swim puts "All duck can swim." end end
However, not all duck are fly in the same way. MallarDuck and RedheadDuck will be able to fly with wing, while ToyDuck won't be able to quack or fly at all. To be able to share same behavior between MallardDuck and RedheadDuck, we create a module under then namespace Behavior
module Behavior module FlyWithWing def fly puts "Fly with wing" end end end module Behavior module NotFly def fly puts "no way I can fly" end end end class MallardDuck < Duck include Behavior::FlyWithWing def initialize @name = 'Mallard duck' end end class RedheadDuck < Duck include Behavior::FlyWithWing def initialize @name = 'Redhead duck' end end class ToyDuck < Duck include Behavior::NotFly def initialize @name = 'Toy duck' end end irb> ducks = [MallardDuck.new, RedHeadDuck.new, ToyDuck.new] irb> ducks.each(&:fly) Fly with wing Fly with wing no way I can flyWith proper directory setup, and follow convention. Ruby will be able to find the file that contain module and include it properly with no configuration at all.
In this case, each module would contain in each file under directory "behavior". By ruby convention, filename would have to match the module name. That mean the file would be name "fly_with_wing.rb", and "not_fly.rb"
We can also do the same with "quack" behavior, say Behavior::QuackLoudly, Behavior::NotQuack, etc.
As you can see, we can use ruby module to implement composition quite efficiently. It's seem natural to me to use module to break down object into different component and composed them.
Next time, I will describe more in detail of the implementation.
[1] Head First Design Patterns, Eric Freema, Elisabeth Freeman, O'Reilly 2004.
No comments:
Post a Comment