SDSU CS 535 Object-Oriented Programming
Spring Semester, 2003
Observer
Previous    Lecture Notes Index    Next    
© 2003, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 26-Mar-03

Contents of Doc 15, Observer



References

Design Patterns: Elements of Reusable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides, pp18-20, 293-304

Ralph Johnson’s Object-Oriented Programming & Design lecture notes, Observer (Day 13) http://st-www.cs.uiuc.edu/users/cs497/lectures.html


Doc 15, Observer Slide # 2

Observer Pattern


Define a one-to-many dependency between objects

When one object changes state all its dependents are notified and updated automatically


Publish-subscribe
Event Handler
Dependence mechanism



Doc 15, Observer Slide # 3
Basic Steps


   subject addDependent: observer


   self changed.
   self changed: #someValue


   define update: aSymbol



Doc 15, Observer Slide # 4

Example


Classes

Boiler – maintains a pressure
Gauge – displays the pressure
SafetyValve – Releases pressure if too high


Doc 15, Observer Slide # 5
Boiler

Smalltalk defineClass: #Boiler
   superclass: #{UI.Model}
   indexedType: #none
   private: false
   instanceVariableNames: 'pressure maximumPressure '
   classInstanceVariableNames: ''
   imports: ''
   category: 'CS535'

Boiler class methodsFor: 'instance creation'

new
   ^super new initialize 

Boiler Instance Methods

addHeat
   self changePressureBy: 15

changePressureBy: aNumber
   pressure :=pressure + aNumber.
   self changed: #pressure.
   pressure > maximumPressure ifTrue:[self changed: #overPressure]

initialize
   pressure := 10.
   maximumPressure := 25.

pressure
   ^pressure 


Doc 15, Observer Slide # 6
Gauge
Smalltalk defineClass: #Gauge
   superclass: #{Core.Object}
   indexedType: #none
   private: false
   instanceVariableNames: 'subject '
   classInstanceVariableNames: ''
   imports: ''
   category: 'CS535'

Gauge class methodsFor: 'instance creation'

subject: aBoiler
   ^super new setSubject: aBoiler 


Gauge Instance Methods

setSubject: aBoiler
   subject :=aBoiler.
   subject addDependent: self

update: aSymbol 
   "Display pressure"

   aSymbol = #pressure 
      ifTrue: 
         [Transcript
            print: subject pressure;
            cr;
            flush] 

Doc 15, Observer Slide # 7
SafetyValue
Smalltalk defineClass: #SafetyValue
   superclass: #{Core.Object}
   indexedType: #none
   private: false
   instanceVariableNames: 'boiler '
   classInstanceVariableNames: ''
   imports: ''
   category: 'CS535'
SafetyValue class methodsFor: 'instance creation'

subject: aBoiler
   ^super new setSubject: aBoiler 
SafetyValue Instance Methods

setSubject: aBoiler
   boiler := aBoiler.
   boiler addDependent: self

update: aSymbol
   aSymbol = #overPressure ifTrue:[boiler changePressureBy: -10]


Doc 15, Observer Slide # 8
Sample Use

boiler := Boiler new.
gauge := Gauge subject: boiler.
valve := SafetyValue subject: boiler.
boiler
   addHeat;
   addHeat;
   addHeat;
   addHeat 

Output In Transcript
25
40
30
20
35
25
40
30
20

Doc 15, Observer Slide # 9
Observer Pattern

Advantages



Disadvantages




Doc 15, Observer Slide # 10
Object Verses Model

Object supports subject behavior

Do not need to make subject class (Boiler) subclass of Model

Using model is cleaner

Object’s dependants list can cause memory leaks

Object uses global dictionary to store dependents

Subject must release its observers/dependents


Doc 15, Observer Slide # 11

ValueModels


Encapsulates model(subject) behavior

A model with two messages to change value

   value
   value:

ValueModel>>onChangeSend: aSymbol to: anObject

   “Arrange to send aSymbol to anObject when receiver changes”
a asValue 
Creates a ValueHolder, subclass of ValueModel, on a

Doc 15, Observer Slide # 12
Example
Smalltalk defineClass: #Boiler
   superclass: #{Core.Object}
   indexedType: #none
   private: false
   instanceVariableNames: 'pressure '
   classInstanceVariableNames: ''
   imports: ''
   category: 'CS535'

Boiler class methodsFor: 'instance creation'

new
   ^super new initialize 

Boiler Instance Methods

addHeat
   self changePressureBy: 15

changePressureBy: aNumber
   pressure value: (pressure value + aNumber)

initialize
   pressure := 10 asValue.

pressure
   ^pressure value

pressureHolder
   ^pressure 

Doc 15, Observer Slide # 13

Smalltalk defineClass: #Gauge
   superclass: #{Core.Object}
   indexedType: #none
   private: false
   instanceVariableNames: 'value '
   classInstanceVariableNames: ''
   imports: ''
   category: 'CS535'

Gauge class methodsFor: 'instance creation'

subject: aValue
   ^super new setSubject: aValue


Gauge Instance Methods

display
    Transcript
      print: value value;
      cr;
      flush

setSubject: aValue
   value := aValue.
   value  onChangeSend: #display to: self 

Doc 15, Observer Slide # 14
Smalltalk defineClass: #SafetyValue superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: 'boiler maximumPressure ' classInstanceVariableNames: '' imports: '' category: 'CS535'

SafetyValue class methodsFor: 'instance creation'

subject: aBoiler
   ^super new setSubject: aBoiler 

SafetyValue Instance Methods

checkPressure
   boiler pressure > maximumPressure ifTrue: [self reducePressure]

reducePressure
   boiler changePressureBy: -10

setSubject: aBoiler
   boiler := aBoiler.
   boiler pressureHolder onChangeSend: #checkPressure to: self.
   maximumPressure := 25 

Doc 15, Observer Slide # 15
Inheritance & Composition

Inheritance






Object Composition






Doc 15, Observer Slide # 16
Inheritance Advantages

Inheritance is defined at compile time

Simple to use

Subclasses can modify behavior of parent class


Object Composition

Can change at runtime

Enforces encapsulation







Copyright ©, All rights reserved.
2003 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.

Previous    visitors since 26-Mar-03    Next