Observer Design Patter in Ruby
Observer Design Patter in Ruby With this article, i want to show you guy about software design, and how to design it in ruby. Design patterns have always been a vital part of a quality software development. In fact, they let developers to work in a team effectively by setting up the common ...
Observer Design Patter in Ruby
With this article, i want to show you guy about software design, and how to design it in ruby. Design patterns have always been a vital part of a quality software development. In fact, they let developers to work in a team effectively by setting up the common ground rules for a problem.
I. Observer Design
And in this post I’d like to introduce you to The Observer Pattern. Basically, observer is a behavioral type, or publish/subscribe pattern which allows a number of observer objects to see an event. So, if an observer object is subscribed to an event on the subject, on a change/update of that event on subject will publish/reflect the changes on the observing objects as well.
How To Use It
I will give you one problem and show the code why we need to use it. For example: An electric bulb’s state(on/off) will depend on the state of the switch it is directly connected to. So, if I turn the switch on then the bulb will be turned on, and vice-a-versa.
Now, think switch and bulb as objects. These objects will have two states: either on or off. However, the bulb’s state will entirely depend on the switch’s state.
Bored reading theoretical stuff?? Let’s see some code in action:
class Appliance attr_accessor :name, :state , :switch def initialize(name, switch = nil) @name = name @state = switch.nil? ? :off : switch.state @switch = switch end def update(changed_state) self.state = changed_state end def on? self.state == :on end def off? self.state == :off end End
Code above shows an Appliance class, which I thought makes more sense. Since, we have bulb, fan, A.C. which are ultimately electrical appliances which have different attributes(of course) except one, which is the state(on/off).
One thing you’ll notice when you see your switch is that, it is integrated on a switch box, so here is our switch box:
class SwitchBox attr_accessor :name, :switches def initialize name @name = name @switches = [] end end
And before we have our switch, we would need the observer:
module Observer attr_reader :observers def initialize @observers = [] end def add_observer observer @observers << observer end def delete_observer observer @observers.delete observer end def notify_observers method = :update self.observers.map do |observer| if observer.respond_to? method observer.send method, self.state else raise NoMethodError, "undefinded method #{method.to_s}" end end end end
Finally we have our switch code as below:
class Switch include Observer attr_reader :name, :state STATES = { :off => :on, :on => :off } def initialize name, state = :off super() @name = name @state = state end def state=(new_state) return if self.state == new_state @state = new_state notify_observers end def on? self.state == :on end def off? self.state == :off end def change_state self.state = STATES[state] end end
Yes, that is all we do, now we can run these code in our terminal
switch_box = SwitchBox.new argf.gets.chomp switch1 = Switch.new argf.gets.chomp, :off switch_box.switches << switch1 appliance = Appliance.new(argf.gets.chomp) appliance.switch = switch1 switch1.add_observer(appliance) puts "Switch named '#{switch1.name}' is currently #{switch1.state.to_s.upcase}" puts "Appliance '#{appliance.name}' is currently #{appliance.state.to_s.upcase}" puts '-'*10 puts 'Changing switch state!!' switch1.state = :on puts 'Switch state has been changed!!' puts '-'*10 puts "Switch named '#{switch1.name}' is now #{switch1.state.to_s.upcase}" puts "Appliance '#{appliance.name}' is now #{appliance.state.to_s.upcase}
Conclusion
This article demonstrated how the Observer Pattern can be used with Ruby, and I hope the example presented here can give you the basic for implementing them on your own applications.
Document:
- http://ruby-doc.org/stdlib-1.9.3/libdoc/observer/rdoc/Observable.html
- http://www.sitepoint.com/design-patterns-in-ruby-observer-singleton/