| |||
Previous < | Contents ^ |
Next > |
each
.
Library: delegate |
Delegator
class implements a simple but powerful delegation scheme, where requests are automatically forwarded from a master class to delegates or their ancestors, and where the delegate can be changed at runtime with a single method call.
The delegate.rb
library provides two mechanisms for allowing an object to forward messages to a delegate.
DelegateClass
, passing the name of the class to be delegated as a parameter (Example 1). Then, in your class's initialize
method, you'd call the superclass, passing in the object to be delegated. For example, to declare a class Fred
that also supports all the methods in Flintstone
, you'd write
class Fred < DelegateClass(Flintstone) def initialize # ... super(Flintstone.new(...)) end # ... end |
SimpleDelegator
(Example 2). You can also add delegation capabilities to an existing object using SimpleDelegator
(Example 3). In these cases, you can call the __setobj__
method in SimpleDelegator
to change the object being delegated at runtime.
DelegateClass
method and subclass the result when you need a class with its own behavior that also delegates to an object of another class. In this example, we assume that the @sizeInInches
array is large, so we want only one copy of it. We then define a class that accesses it, converting the values to feet.
require 'delegate' sizeInInches = [ 10, 15, 22, 120 ] class Feet < DelegateClass(Array) def initialize(arr) super(arr) end def [](*n) val = super(*n) case val.type when Numeric; val/12.0 else; val.collect {|i| i/12.0} end end end |
sizeInFeet = Feet.new(sizeInInches) | ||
sizeInInches[0..3] |
» | [10, 15, 22, 120] |
sizeInFeet[0..3] |
» | [0.8333333333, 1.25, 1.833333333, 10.0] |
SimpleDelegator
when you want an object that both has its own behavior and delegates to different objects during its lifetime. This is an example of the State pattern. Objects of class TicketOffice
sell tickets if a seller is available, or tell you to come back tomorrow if there is no seller.
require 'delegate' class TicketSeller def sellTicket() return 'Here is a ticket' end end class NoTicketSeller def sellTicket() "Sorry-come back tomorrow" end end class TicketOffice < SimpleDelegator def initialize @seller = TicketSeller.new @noseller = NoTicketSeller.new super(@seller) end def allowSales(allow = true) __setobj__(allow ? @seller : @noseller) allow end end |
to = TicketOffice.new | ||
to.sellTicket |
» | "Here is a ticket" |
to.allowSales(false) |
» | false |
to.sellTicket |
» | "Sorry-come back tomorrow" |
to.allowSales(true) |
» | true |
to.sellTicket |
» | "Here is a ticket" |
SimpleDelegator
objects when you want a single object to delegate all its methods to two or more other objects.
# Example 3 - delegate from existing object | ||
seller = TicketSeller.new | ||
noseller = NoTicketSeller.new | ||
to = SimpleDelegator.new(seller) | ||
to.sellTicket |
» | "Here's a ticket" |
to.sellTicket |
» | "Here's a ticket" |
to.__setobj__(noseller) | ||
to.sellTicket |
» | "Sorry-come back tomorrow" |
to.__setobj__(seller) | ||
to.sellTicket |
» | "Here's a ticket" |
Library: observer |
Observable
module, which provides the methods for managing the associated observer objects.
add_observer(obj) | Add obj as an observer on this object. obj will now receive notifications. | |||||||
delete_observer(obj) | Delete obj as an observer on this object. It will no longer receive notifications. | |||||||
delete_observers | Delete all observers associated with this object. | |||||||
count_observers | Return the count of observers associated with this object. | |||||||
changed(newState=true ) |
Set the changed state of this object. Notifications will be sent only if the changed state is true . | |||||||
changed? | Query the changed state of this object. | |||||||
notify_observers(*args) | If this object's changed state is true, invoke the update method in each currently associated observer in turn, passing it the given arguments. The changed state is then set to false . | |||||||
update
method to receive notifications.
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 end end end class Warner def initialize(ticker, limit) @limit = limit ticker.add_observer(self) # all warners are observers 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 |
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 |
Library: singleton |
singleton
library makes this simple to implement. Mix the Singleton
module into each class that is to be a singleton, and that class's new
method will be made private. In its place, users of the class call the method instance
, which returns a singleton instance of that class.
In this example, the two instances of MyClass
are the same object.
require 'singleton' | ||
| ||
class MyClass | ||
include Singleton | ||
end | ||
| ||
a = MyClass.instance |
» | #<MyClass:0x401b4ca8> |
b = MyClass.instance |
» | #<MyClass:0x401b4ca8> |
Previous < | Contents ^ |
Next > |