Path: | lib/observer.rb |
Last Update: | Tue Jun 30 13:22:25 -0700 2009 |
observer.rb implements the Observer object-oriented design pattern. The following documentation is copied, with modifications, from "Programming Ruby", by Hunt and Thomas; www.rubycentral.com/book/lib_patterns.html.
The Observer pattern, also known as Publish/Subscribe, provides a simple mechanism for one object to inform a set of interested third-party objects when its state changes.
In the Ruby implementation, the notifying class mixes in the Observable module, which provides the methods for managing the associated observer objects.
The observers must implement the update method to receive notifications.
The observable object must:
The following example demonstrates this nicely. A Ticker, when run, continually receives the stock Price for its +@symbol+. A Warner is a general observer of the price, and two warners are demonstrated, a WarnLow and a WarnHigh, which print a warning if the price is below or above their set limits, respectively.
The update callback allows the warners to run without being explicitly called. The system is set up with the Ticker and several observers, and the observers do their duty without the top-level code having to interfere.
Note that the contract between publisher and subscriber (observable and observer) is not declared or enforced. The Ticker publishes a time and a price, and the warners receive that. But if you don‘t ensure that your contracts are correct, nothing else can warn you.
require "observer" class Ticker ### Periodically fetch a stock price. include Observable def initialize(symbol) @symbol = symbol end def run lastPrice = nil loop do price = Price.fetch(@symbol) print "Current price: #{price}\n" if price != lastPrice changed # notify observers lastPrice = price notify_observers(Time.now, price) end sleep 1 end end end class Price ### A mock class to fetch a stock price (60 - 140). def Price.fetch(symbol) 60 + rand(80) end end class Warner ### An abstract observer of Ticker objects. def initialize(ticker, limit) @limit = limit ticker.add_observer(self) end end class WarnLow < Warner def update(time, price) # callback for observer if price < @limit print "--- #{time.to_s}: Price below #@limit: #{price}\n" end end end class WarnHigh < Warner def update(time, price) # callback for observer if price > @limit print "+++ #{time.to_s}: Price above #@limit: #{price}\n" end end end ticker = Ticker.new("MSFT") WarnLow.new(ticker, 80) WarnHigh.new(ticker, 120) ticker.run
Produces:
Current price: 83 Current price: 75 --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75 Current price: 90 Current price: 134 +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134 Current price: 134 Current price: 112 Current price: 79 --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79
ruby-doc.org is a service of James Britt and Neurogami, a Ruby application development company in Phoenix, AZ.
Documentation content on ruby-doc.org is provided by remarkable members of the Ruby community.
For more information on the Ruby programming language, visit ruby-lang.org.
Want to help improve Ruby's API docs? See Ruby Documentation Guidelines.