Skip to content

The Dependency Mechanism 3

Dr. Nicola Mingotti edited this page Jan 23, 2022 · 13 revisions
  • In Cuis the dependency is handled with the  Observer pattern
  • In the observer pattern an object called subject maintains a list of observers. The subject notifies its observers when it changes.
  • In Cuis the Parent-Dependent pattern is implemented with the Subject-Observer this way
  Parent-Dependent Subject-Observer
connection making. objB wants to be informed of changes in objA. objA addDependent: objB objA when: #changed send: #update to: objB
objA tells the objects who are watching it that it changed state. objA changed: #param objA triggerEvent: #changed with: #param
when  objA state changes the message update is sent to objB with a parameter. objB update: #param objB update: #param
we want objB to stop watching objA objA removeDependent: objB objA removeActionWithReceiver: objB forEvent: #changed
  • Observe that the parameter #changed is used explicitly in Cuis to build Parent-Dependent pattern, but that is actually a free parameter in the Observer model.
  • In Cuis6 Model is substituted by ActiveModel, if you look into the implementation of the Parent-Dependent pattern you will see that dependencies between objects go by default stored in class variable ActionMaps of ActiveModel . This instead of using class variable DependentsFields of class Object, as done in the classic implementation, for example in VisualWorks and Squeak.
  • Exercise. Use ActiveModel actionMaps to explore the ActionMaps class variable content.
  • Mirroring our previous example in the Parent-Dependent model, we impolement of two simple classes (in the Subject-Observer model) MyActiveNumber and MyObserverNumber for objects objA and objB, where objB is observer for objA. We want to keep the dependency mechanism localized so MyActiveNumber will be subclass of ActiveModel (instead of Object). When objA changes we want objB to receive the message update, we don't want to pass any parameter, objB will ask what it need to objA. You can get the fileout here: MyActiveNumber.st and MyObserverNumber.st .
ActiveModel subclass: #MyActiveNumber
    instanceVariableNames: 'value'

MyActiveNumber >> initialize
    value := 0. 
    ^ self 

MyActiveNumber >> value 
        ^ value 

MyActiveNumber >> value: aNumber        
        value := aNumber
        self triggerEvent: #iChanged 

Object subclass: #MyObserverNumber
    instanceVariableNames: 'value model'  

MyObserverNumber class >> newWithModel: anObject
    ^ super new initializeWithModel: anObject

MyObserverNumber >> initializeWithModel: anObject
    value := 0.
    model := anObject . 
    model when: #iChanged send: #update  to: self .  
    ^ self     

MyObserverNumber update
    |vPar vMe |
     vPar := model value. 
     vMe := vPar * 2.
     value := vMe.
     Transcript show: ('my MODEL value is:{1} and mine is value:{2}' format: {vPar. vMe} ). 

MyObserverNumber value
         ^ value                                            
  • Then try everything works with a little interaction from the Workspace
objA := MyActiveNumber new. 
objB := MyObserverNumber newWithModel: objA. 

objA value .  "=> 0"
objB value.   "=> 0"

objA value: 10.  

objB value. "=> 20" 
  • Exercise. explore objA and convince your self it contains the map toward object objB.
Clone this wiki locally