ÿØÿà JFIF    ÿÛ „ ( %!1!%*+...983,7(-.- PKÝN]fÙ¡Ñ``count_observers-i.rinu„[µü¤U:RDoc::AnyMethod[iI"count_observers:EFI"Observable#count_observers;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"@Return the number of observers associated with this object.;T: @fileI"lib/observer.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI"Observable;FcRDoc::NormalModule00PKÝN]èe¨XXdelete_observers-i.rinu„[µü¤U:RDoc::AnyMethod[iI"delete_observers:EFI" Observable#delete_observers;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"6Remove all observers associated with this object.;T: @fileI"lib/observer.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI"Observable;FcRDoc::NormalModule00PKÝN]À ¿B··add_observer-i.rinu„[µü¤U:RDoc::AnyMethod[iI"add_observer:EFI"Observable#add_observer;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KAdd +observer+ as an observer on this object. so that it will receive ;TI"notifications.;To:RDoc::Markup::BlankLineo:RDoc::Markup::List: @type: NOTE: @items[o:RDoc::Markup::ListItem: @label[I"+observer+;T; [o; ; [I"1the object that will be notified of changes.;To;;[I" +func+;T; [o; ; [I"GSymbol naming the method that will be called when this Observable ;TI"has changes.;T@o; ; [ I"FThis method must return true for +observer.respond_to?+ and will ;TI"Creceive *arg when #notify_observers is called, where ;TI"D*arg is the value passed to #notify_observers by this ;TI"Observable;T: @fileI"lib/observer.rb;T:0@omit_headings_from_table_of_contents_below000[I"(observer, func=:update);T@'FI"Observable;FcRDoc::NormalModule00PKÝN]R¡7¤]]cdesc-Observable.rinu„[µü¤U:RDoc::NormalModule[iI"Observable:EF@0o:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"NThe Observer pattern (also known as publish/subscribe) provides a simple ;TI"Pmechanism for one object to inform a set of interested third-party objects ;TI"when its state changes.;To:RDoc::Markup::BlankLineS:RDoc::Markup::Heading: leveli: textI"Mechanism;T@o; ;[I"3The notifying class mixes in the +Observable+ ;TI"Mmodule, which provides the methods for managing the associated observer ;TI" objects.;T@o; ;[I" The observable object must:;To:RDoc::Markup::List: @type: BULLET: @items[o:RDoc::Markup::ListItem: @label0;[o; ;[I""assert that it has +#changed+;To;;0;[o; ;[I"call +#notify_observers+;T@o; ;[I"QAn observer subscribes to updates using Observable#add_observer, which also ;TI"Ospecifies the method called via #notify_observers. The default method for ;TI""#notify_observers is #update.;T@S; ; i; I" Example;T@o; ;[ I"LThe following example demonstrates this nicely. A +Ticker+, when run, ;TI"Rcontinually receives the stock +Price+ for its @symbol. A +Warner+ ;TI"Mis a general observer of the price, and two warners are demonstrated, a ;TI"P+WarnLow+ and a +WarnHigh+, which print a warning if the price is below or ;TI"*above their set limits, respectively.;T@o; ;[I"NThe +update+ callback allows the warners to run without being explicitly ;TI"Tcalled. The system is set up with the +Ticker+ and several observers, and the ;TI"Lobservers do their duty without the top-level code having to interfere.;T@o; ;[ I"MNote that the contract between publisher and subscriber (observable and ;TI"Qobserver) is not declared or enforced. The +Ticker+ publishes a time and a ;TI"Mprice, and the warners receive that. But if you don't ensure that your ;TI"6contracts are correct, nothing else can warn you.;T@o:RDoc::Markup::Verbatim;[>I"require "observer" ;TI" ;TI"Aclass Ticker ### Periodically fetch a stock price. ;TI" include Observable ;TI" ;TI" def initialize(symbol) ;TI" @symbol = symbol ;TI" end ;TI" ;TI" def run ;TI" last_price = nil ;TI" loop do ;TI"( price = Price.fetch(@symbol) ;TI"- print "Current price: #{price}\n" ;TI"" if price != last_price ;TI"8 changed # notify observers ;TI" last_price = price ;TI"/ notify_observers(Time.now, price) ;TI" end ;TI" sleep 1 ;TI" end ;TI" end ;TI" end ;TI" ;TI"Oclass Price ### A mock class to fetch a stock price (60 - 140). ;TI" def self.fetch(symbol) ;TI" 60 + rand(80) ;TI" end ;TI" end ;TI" ;TI"Gclass Warner ### An abstract observer of Ticker objects. ;TI"% def initialize(ticker, limit) ;TI" @limit = limit ;TI"# ticker.add_observer(self) ;TI" end ;TI" end ;TI" ;TI"class WarnLow < Warner ;TI"= def update(time, price) # callback for observer ;TI" if price < @limit ;TI"E print "--- #{time.to_s}: Price below #@limit: #{price}\n" ;TI" end ;TI" end ;TI" end ;TI" ;TI"class WarnHigh < Warner ;TI"= def update(time, price) # callback for observer ;TI" if price > @limit ;TI"E print "+++ #{time.to_s}: Price above #@limit: #{price}\n" ;TI" end ;TI" end ;TI" end ;TI" ;TI"!ticker = Ticker.new("MSFT") ;TI"WarnLow.new(ticker, 80) ;TI"WarnHigh.new(ticker, 120) ;TI"ticker.run ;T: @format0o; ;[I"Produces:;T@o;;[I"Current price: 83 ;TI"Current price: 75 ;TI":--- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75 ;TI"Current price: 90 ;TI"Current price: 134 ;TI"<+++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134 ;TI"Current price: 134 ;TI"Current price: 112 ;TI"Current price: 79 ;TI"9--- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79;T;0: @fileI"lib/observer.rb;T:0@omit_headings_from_table_of_contents_below0;0;0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[;[ [I"add_observer;FI"lib/observer.rb;T[I" changed;F@›[I" changed?;F@›[I"count_observers;F@›[I"delete_observer;F@›[I"delete_observers;F@›[I"notify_observers;F@›[;[[;[[[U:RDoc::Context::Section[i0o;;[;0;0[@†@†cRDoc::TopLevelPKÝN]±˜BBdelete_observer-i.rinu„[µü¤U:RDoc::AnyMethod[iI"delete_observer:EFI"Observable#delete_observer;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"ORemove +observer+ as an observer on this object so that it will no longer ;TI"receive notifications.;To:RDoc::Markup::BlankLineo:RDoc::Markup::List: @type: NOTE: @items[o:RDoc::Markup::ListItem: @label[I"+observer+;T; [o; ; [I"#An observer of this Observable;T: @fileI"lib/observer.rb;T:0@omit_headings_from_table_of_contents_below000[I"(observer);T@FI"Observable;FcRDoc::NormalModule00PKÝN]âËóayychanged%3f-i.rinu„[µü¤U:RDoc::AnyMethod[iI" changed?:EFI"Observable#changed?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"IReturns true if this object's state has been changed since the last ;TI"#notify_observers call.;T: @fileI"lib/observer.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI"Observable;FcRDoc::NormalModule00PKÝN]ö`ñqSS changed-i.rinu„[µü¤U:RDoc::AnyMethod[iI" changed:EFI"Observable#changed;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"OSet the changed state of this object. Notifications will be sent only if ;TI"#the changed +state+ is +true+.;To:RDoc::Markup::BlankLineo:RDoc::Markup::List: @type: NOTE: @items[o:RDoc::Markup::ListItem: @label[I" +state+;T; [o; ; [I"=Boolean indicating the changed state of this Observable.;T: @fileI"lib/observer.rb;T:0@omit_headings_from_table_of_contents_below000[I"(state=true);T@FI"Observable;FcRDoc::NormalModule00PKÝN]¢=óÉÉnotify_observers-i.rinu„[µü¤U:RDoc::AnyMethod[iI"notify_observers:EFI" Observable#notify_observers;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"ONotify observers of a change in state *if* this object's changed state is ;TI" +true+.;To:RDoc::Markup::BlankLineo; ; [I"PThis will invoke the method named in #add_observer, passing *arg. ;TI".The changed state is then set to +false+.;T@o:RDoc::Markup::List: @type: NOTE: @items[o:RDoc::Markup::ListItem: @label[I"*arg;T; [o; ; [I",Any arguments to pass to the observers.;T: @fileI"lib/observer.rb;T:0@omit_headings_from_table_of_contents_below000[I" (*arg);T@FI"Observable;FcRDoc::NormalModule00PKÝN]fÙ¡Ñ``count_observers-i.rinu„[µü¤PKÝN]èe¨XX¤delete_observers-i.rinu„[µü¤PKÝN]À ¿B··Aadd_observer-i.rinu„[µü¤PKÝN]R¡7¤]]9cdesc-Observable.rinu„[µü¤PKÝN]±˜BBÙdelete_observer-i.rinu„[µü¤PKÝN]âËóayy_changed%3f-i.rinu„[µü¤PKÝN]ö`ñqSS changed-i.rinu„[µü¤PKÝN]¢=óÉɦnotify_observers-i.rinu„[µü¤PK‘´"