|
|||
each.
| Library: delegate |
Delegator implementa un sencillo pero potente
esquema de delegación, donde las solicitudes se pasan automáticamente desde una clase maestra
a una de sus delegadas o sus ancestros, y donde la delegación
puede ser modificada en tiempo de ejecución con una simple llamada a un método.
La librería delegate.rb proporciona dos mecanismos para permitir a un
objeto enrutar mensajes a un delegado.
DelegateClass, pasándole el nombre de la clase
delegada como parámetro (Ejemplo 1). Después, en el método
initialize de tu clase, llamarías a su superclase, pasándole
el objeto que debe ser delegado. Por ejemplo, para declarar una clase
Fred que también soporte todos los métodos en Flintstone, escribirías
class Fred < DelegateClass(Flintstone) def initialize # ... super(Flintstone.new(...)) end # ... end |
SimpleDelegator (Ejemplo 2). Puedes
también añadir capacidades de delegación a un objeto existente usando
SimpleDelegator (Ejemplo 3). En estos casos, puedes llamar al método
__setobj__ en SimpleDelegator para cambiar
el objeto delegado en tiempo de ejecución.
DelegateClass y haz una
subclase del valor devuelto cuando necesites una clase con su propio comportamiento
que también delega a un objeto de otra clase. En este ejemplo, asumimos
que el array @sizeInInches es grande, por lo que queremos que solo
exista una copia de él. Después definimos una clase que accede a él convirtiendo
los valores a pies.
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 cuando necesites
un objeto que tiene su propio comportamiento y delega a
diferentes objectos durante su tiempo de vida. Éste es un ejemplo del
patrón Estado.
Los objetos de la calse TicketOffice venden tickets si
hay un vendedor disponible, o te dicen que vuelvas mañana si no lo hay.
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 cuando necesites
un solo objeto que delega todos sus métodos a dos o más objetos diferentes.
# 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, el cual proporciona los métodos para gestionar
los objetos observadores asociados.
| add_observer(obj) | Añade obj como observador de este objeto. obj recibirá las notificaciones. | |||||||
| delete_observer(obj) | Elimina obj como observador de este objeto. Ya no recibirá más notificaciones. | |||||||
| delete_observers | Elimina todos los observadores asociados con este objeto. | |||||||
| count_observers | Devuelve el número de observadores asociados con este objeto. | |||||||
changed(nuevoEstado=true) |
Establece el estado de modificado del objeto.
Se enviarán las notificaciones solamente si el estado de modificado es
true. |
|||||||
| changed? | Comprueba el estado de modificado del objeto. | |||||||
| notify_observers(*args) | Si el estado de modificado del objeto es
true, invoca el método update en cada uno de los observadores asociados,
pasándoles los argumentos dados. El estado de modificado
se establece a continuación a false. |
|||||||
update para recibir
las notificaciones.
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 hace que ésto sea sencillo de implementar. Añade el módulo
Singleton dentro de cada clase que debe ser singleton,
y el método new de la clase se hará privado. En su lugar,
los usuarios de la clase llamarán al método instance, el cual
devuelve una instancia singleton de esa clase.
En este ejmplo, las dos instancias de MyClass son el mismo objeto.
require 'singleton'
|
||
|
||
class MyClass
|
||
include Singleton
|
||
end
|
||
|
||
a = MyClass.instance
|
» |
#<MyClass:0x401b4ca8>
|
b = MyClass.instance
|
» |
#<MyClass:0x401b4ca8>
|