|
|||
each
.
Library: delegate |
Delegator
-Klasse in Ruby realisiert ein einfaches
aber wirkungsvolles Schema, mit der Anfragen automatisch von einer Master-Klasse an
Deligierte weitergeleitet werden können, wobei die Delegierten zu Laufzeit mit
einem einfachen Methoden-Aufruf geändert werden können.
Die delegate.rb
-Bibliothek unterstützt zwei Mechanismen, mit denen ein
Objekt eine Meldung an einen Delegierten reichen kann.
DelegateClass
ein und
übergibt dabei den Namen des Delegierten als Parameter (Beispiel 1). Danach ruft man in
der initialize
-Methode der Master-Klasse die Oberklasse auf und übergibt ihr
das Delegierten-Objekt. Als Beispiel deklarieren wir die Klasse
Fred
, die auch alle Methoden aus Flintstone
unterstützen soll:
class Fred < DelegateClass(Flintstone) def initialize # ... super(Flintstone.new(...)) end # ... end |
SimpleDelegator
(Beispiel 2). Man kann mit SimpleDelegator
die Fähigkeit der
Delegation auch einem schon existierenden Objekt hinzufügen (Beispiel 3). In beiden
Fällen ruft man die Methode __setobj__
in
SimpleDelegator
auf, um das Delegierten-Objekt zur Laufzeit zu
ändern.
DelegateClass
-Methode und
erzeugt mit dem Ergebnis eine Unterklasse. In diesem Beispiel nehmen wir an, dass
das sizeInInches
-Array sehr groß ist, so dass wir nur ein Exemplar
davon haben wollen. Dazu definieren wir eine darauf zugreifende Klasse, die die
Werte in Feet umrechnet.
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
,
wenn man ein Objekt braucht, das sein eigenes Verhalten besitzt und
zusätzlich unterschiedliche Objekte delegieren soll. Dies ist auch ein Beispiel für ein
Zustandsmuster. Objekte der Klasse TicketOffice
verkaufen
Tickets wenn ein Verkäufer vorhanden ist, oder sagen, dass man wiederkommen soll,
wenn keiner vorhanden ist.
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
-Objekte, wenn
man möchte, dass ein einzelnes Objekt alle seine Methoden an zwei oder mehr andere
Objekte delegiert.
# 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
-Modul ein, das die Methoden zum Verwalten der
zugehörenden Beobachter-Klassen verwaltet.
add_observer(obj) | Füge obj als ein Beobachter dieses Objektes hinzu. obj bekommt ab jetzt Mitteilungen. | |||||||
delete_observer(obj) | Lösche obj als Beobachter dieses Objektes. Es bekommt ab jetzt keine Mitteilungen mehr. | |||||||
delete_observers | Lösche alle mit diesem Objekt verbundenen Beobachter. | |||||||
count_observers | Liefert die Anzahl der mit diesem Objekt verbundenen Beobachter. | |||||||
changed(newState=true ) |
Setzt den Changed-Status dieses Objektes. Mitteilungen werden nur gesendet, wenn der
Change-Status true ist. |
|||||||
changed? | Fragt den Changed-Status dieses Objektes ab. | |||||||
notify_observers(*args) | Falls der Changed-Status dieses Objektes true ist, so rufe die
update -Methode von jedem zur Zeit angeschlossenen Beobachter auf und
übergib ihr die angegebenen Argumente. Der Changed-Status wird danach auf
false gesetzt. |
|||||||
update
-Methode implementieren, um Mitteilungen
empfangen zu können.
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 [email protected]: #{price}\n" end end end class WarnHigh < Warner def update(time, price) # callback for observer if price > @limit print "+++ #{time.to_s}: Price above [email protected]: #{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 Mar 04 23:26:31 CST 2001: Price below 80: 75 Current price: 90 Current price: 134 +++ Sun Mar 04 23:26:31 CST 2001: Price above 120: 134 Current price: 134 Current price: 112 Current price: 79 --- Sun Mar 04 23:26:31 CST 2001: Price below 80: 79 |
Library: singleton |
singleton
-Bibliothek macht die Implemantation einfach. Man mischt einfach
das Modul Singleton
zu jeder Klasse bei, die ein Singleton
werden soll, und die new
-Methode dieser Klasse wird privat. An seiner
Stelle tritt die Methode instance
, die eine Singleton-Instanz der Klasse
zurück liefert.
Im folgenden Beispiel sind die beiden Instanzen von MyClass
ein und
dasselbe Objekt.
require 'singleton' |
||
|
||
class MyClass |
||
include Singleton |
||
end |
||
|
||
a = MyClass.instance |
» | #<MyClass:0x4018c924> |
b = MyClass.instance |
» | #<MyClass:0x4018c924> |