Folks, I'm trying to implement an Observer Pattern in Dolphin
Smalltalk, but all the documentation I have is for other distribution (VisualAge, etc). What I'm trying to do is an event correlation object, when some variable from the first object change, the other objects gets the change an follow the first object. I found many examples in Internet, but I'm a litle confuse about the triggers and addDependents, etc.. I would appreciate if you have a clear example how to implement it in dolphin. Thanks. Pablo |
Pablo,
> I found many examples in Internet, but I'm a litle confuse about the > triggers and addDependents, etc.. I would appreciate if you have a > clear example how to implement it in dolphin. In Dolphin any object can trigger an event and any other object can register to receive a notification from the source object when the event is triggered. So, say you have a class called MyWidget and you want to know when a MyWidget object is modified. If all changes to MyWidget can be channeled through one method then you would simply have ... MyWidget>>modify (code to modify this MyWidget object) self trigger: #changed If there were multiple ways (methods) to change MyWidget then each method could trigger the same event _or_ each method could trigger a different event MyWidget>>modifyA (code to modify the A aspect in this MyWidget object) self trigger: #changedA MyWidget>>modifyB (code to modify the B aspect in this MyWidget object) self trigger: #changedB You can also pass one or more arguments so the object triggering the event could either pass the new value or pass itself so that any object being notified would know who triggered it [1] MyWidget>>modifyA (code to modify the A aspect MyWidget object) "NOTE the colon after the Symbol which indicates an argument" self trigger: #changedA: with: self newAValue or MyWidget>>modify "code to modify this MyWidget object" self trigger: #changed: with: self Objects that need to be notified when an object changes would normally register themselves when the MyWidget is created. MyController>>initialize myWidget := MyWidget new. myWidget when: #changed send: #onWidgetChanged to: self MyController>>onWidgetChanged "myWidget has changed" With an argument..... MyController>>initialize myWidget := MyWidget new. "NOTE a colon at the end of each Symbol" myWidget when: #changed: send: #onWidgetChanged: to: self MyController>>onWidgetChanged: anArgument "myWidget has changed" [1] Note that the event symbol used when passing arguments doesn't _need_ to include colons (i.e. be a keyword selector) but it does make thing easier when reading the code. For example, the following would work and pass two arguments MyWidget>>modify "code to modify this MyWidget object" self trigger: #changed with: 1 with: 2 MyController>>initialize myWidget := MyWidget new. myWidget when: #changed send: #onWidgetChanged:with: to: self MyController>>onWidgetChanged: arg1 with: arg2 "arg1 == 1" "arg2 == 2" The dependency mechanism is a separate framework and is not really used in Dolphin. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
Thanks Ian, it works well!. What I'm trying to do is to wire more than one
object to many objects, in your example I understand that is for one object follow by many. What I have here, is very similar to an auction, with many clients with many auctions, and when a price o something from any of the auctions change all the clients needs to be notified. How can I register all the clients with all the auctions ? Thanks again.. PabloS "Ian Bartholomew" <[hidden email]> wrote in message news:[hidden email]... > Pablo, > > > I found many examples in Internet, but I'm a litle confuse about the > > triggers and addDependents, etc.. I would appreciate if you have a > > clear example how to implement it in dolphin. > > In Dolphin any object can trigger an event and any other object can register > to receive a notification from the source object when the event is > triggered. > > So, say you have a class called MyWidget and you want to know when a > MyWidget object is modified. If all changes to MyWidget can be channeled > through one method then you would simply have ... > > MyWidget>>modify > (code to modify this MyWidget object) > self trigger: #changed > > If there were multiple ways (methods) to change MyWidget then each method > could trigger the same event _or_ each method could trigger a different > event > > MyWidget>>modifyA > (code to modify the A aspect in this MyWidget object) > self trigger: #changedA > > MyWidget>>modifyB > (code to modify the B aspect in this MyWidget object) > self trigger: #changedB > > You can also pass one or more arguments so the object triggering the event > could either pass the new value or pass itself so that any object being > notified would know who triggered it [1] > > MyWidget>>modifyA > (code to modify the A aspect MyWidget object) > "NOTE the colon after the Symbol which indicates an argument" > self trigger: #changedA: with: self newAValue > > or > > MyWidget>>modify > "code to modify this MyWidget object" > self trigger: #changed: with: self > > > > Objects that need to be notified when an object changes would normally > register themselves when the MyWidget is created. > > MyController>>initialize > myWidget := MyWidget new. > myWidget when: #changed send: #onWidgetChanged to: self > > MyController>>onWidgetChanged > "myWidget has changed" > > With an argument..... > > MyController>>initialize > myWidget := MyWidget new. > "NOTE a colon at the end of each Symbol" > myWidget when: #changed: send: #onWidgetChanged: to: self > > MyController>>onWidgetChanged: anArgument > "myWidget has changed" > > [1] Note that the event symbol used when passing arguments doesn't _need_ > include colons (i.e. be a keyword selector) but it does make thing easier > when reading the code. For example, the following would work and pass two > arguments > > MyWidget>>modify > "code to modify this MyWidget object" > self trigger: #changed with: 1 with: 2 > > MyController>>initialize > myWidget := MyWidget new. > myWidget when: #changed send: #onWidgetChanged:with: to: self > > MyController>>onWidgetChanged: arg1 with: arg2 > "arg1 == 1" > "arg2 == 2" > > > > The dependency mechanism is a separate framework and is not really used in > Dolphin. > > -- > Ian > > Use the Reply-To address to contact me. > Mail sent to the From address is ignored. > > > > |
Pablo,
> What I have here, is very similar to an auction, with many clients with > many auctions, and when a price o something from any of the auctions change > all the clients needs to be notified. How can I register all the clients > with all the auctions ? Based on the above spec, I'm not sure observers are needed. Presumably, a client joins an auction at some point in time. The auction object can keep a list of active clients (in an instance variable). When the price of some object in the auction is changed, the auction sends a message to each of the clients it knows of. Auction>>addClient: aClient clients add: aClient. Auction>>price: aNumber item: anObject "Set anObject's price to aNumber and notify all clients." anObjet price: aNumber. clients do: [:client | client price: aNumber item: anObject auction: self]. Client>>price: aNumber item: anObject auction: anAuction <client logic goes here> -- Louis |
In reply to this post by PabloS
Pablo,
> What I have here, is very similar to an auction, with many clients > with many auctions, and when a price o something from any of the > auctions change all the clients needs to be notified. How can I > register all the clients with all the auctions ? I'm not quite sure what you are asking here? An object that triggers events (your auction) has no interest in the number of objects (your clients) that have registered to receive the events. It just triggers the event and lets the system sort out who needs to know - if anyone. A client can register with any number of auctions. As all the auctions will trigger the same event then the client needs to know which auction it was - this is when passing the triggerer as an argument is useful.... Auction>>newBid: aNumber (code to accept the bid) self trigger: #newBid with: self with: aNumber Bidder>>initialize (all auctions) when: #newBid send: #onNewBidInAuction:bid: to: self Bidder>>onNewBidInAuction: anAuction bid: aNumber (someone had made a bid of aNumber in anAuction) The bit you may be missing is some sort of "Manager" object that holds the Auctions and Bidders. If you want all auctions to be accessible to all bidders then that would just be a case of AuctionManager>>addBidder: aString | bidder | bidders add: (bidder := Bidder new name: aString). auctions do: [:each | each when: #newBid send: #onNewBidInAuction:bid: to: bidder] AuctionManager>>addAuction: anObject | auction| auctions add: (auction:= Auction new item: anObject). bidders do: [:each | auction when: #newBid send: #onNewBidInAuction:bid: to: each] That will link all auctions to all bidders and whenever a new bid is made in an auction then all the bidders will be notified. If a bidder wasn't interested in an auction then you could have a bit mor code that only linked the two if you knew the bidder would be interested. You could also work it so the "manager" intercepts all new bid notifications .... An Auction triggers an event that is only received by the AuctionManager The AuctionManager then triggers an event that is used by the Bidders. This would give a bigger separation between the Auctions and Bidders and would allow the AuctionManager to do any extra processing (log bids, check bidders limits etc). As I said above, I'm not really sure which bit is causing you a problem so feel free to ask again. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
Thanks Ian/Louis, It works well..
"Ian Bartholomew" <[hidden email]> wrote in message news:[hidden email]... > Pablo, > > > What I have here, is very similar to an auction, with many clients > > with many auctions, and when a price o something from any of the > > auctions change all the clients needs to be notified. How can I > > register all the clients with all the auctions ? > > I'm not quite sure what you are asking here? > > An object that triggers events (your auction) has no interest in the > of objects (your clients) that have registered to receive the events. It > just triggers the event and lets the system sort out who needs to know - if > anyone. > > A client can register with any number of auctions. As all the auctions will > trigger the same event then the client needs to know which auction it was - > this is when passing the triggerer as an argument is useful.... > > Auction>>newBid: aNumber > (code to accept the bid) > self trigger: #newBid with: self with: aNumber > > Bidder>>initialize > (all auctions) when: #newBid send: #onNewBidInAuction:bid: to: self > > Bidder>>onNewBidInAuction: anAuction bid: aNumber > (someone had made a bid of aNumber in anAuction) > > The bit you may be missing is some sort of "Manager" object that holds the > Auctions and Bidders. If you want all auctions to be accessible to all > bidders then that would just be a case of > > AuctionManager>>addBidder: aString > | bidder | > bidders add: (bidder := Bidder new name: aString). > auctions do: [:each | > each when: #newBid send: #onNewBidInAuction:bid: to: bidder] > > AuctionManager>>addAuction: anObject > | auction| > auctions add: (auction:= Auction new item: anObject). > bidders do: [:each | > auction when: #newBid send: #onNewBidInAuction:bid: to: each] > > That will link all auctions to all bidders and whenever a new bid is made > an auction then all the bidders will be notified. If a bidder wasn't > interested in an auction then you could have a bit mor code that only linked > the two if you knew the bidder would be interested. > > You could also work it so the "manager" intercepts all new bid notifications > .... > > An Auction triggers an event that is only received by the AuctionManager > The AuctionManager then triggers an event that is used by the Bidders. > > This would give a bigger separation between the Auctions and Bidders and > would allow the AuctionManager to do any extra processing (log bids, check > bidders limits etc). > > As I said above, I'm not really sure which bit is causing you a problem so > feel free to ask again. > > -- > Ian > > Use the Reply-To address to contact me. > Mail sent to the From address is ignored. > > |
Free forum by Nabble | Edit this page |