280 likes | 419 Views
Observer, Strategy, Decorator, Prototype,. Observer Pattern. Dependence mechanism / publish-subscribe / event handler / constraints / broadcast Let objects propagate information without depending on each other much.
E N D
Observer Pattern • Dependence mechanism / publish-subscribe / event handler / constraints / broadcast • Let objects propagate information without depending on each other much. • Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
Observer Pattern observer/ dependent Subject addDependent: removeDependent: changed: Observer update: model ValueHolder value: value TextView update:
Observer Pattern: • Registration • subject addDependent: observer • Notification • self changed. self changed: #value • Update • define update: aSymbol
Notification • Object notifies dependents when information changes by sending itself a #changed message. • changed: anArg • self dependents • do: [:each | each update: anArg]
Problem • A man and dog are in the room. When the dog wants to go out, he barks. When the man hears the dog barking, he opens the door. When the dog wants to go out and the door is open, he leaves.
Basic classes • Dog • bark / move • Person • Door • open / close / isOpen • Object • addDependent: • changed: • update:
Collaborations Dog bark watch listen Door openclose Person
Dynamic Model Record order of events, interaction between objects. Sequence diagram Dog Person Door register register bark notify open notify go thru door unregister notify close
A Script • | person door dog | • door := Door new close. • dog := Dog new. • dog door: door. • person := Person new. • person door: door; dog: dog. • dog bark.
Door • opened <Boolean> • open • opened := true. • self changed: #open
Door • close • opened := false. • self changed: #close • isOpen • ^opened
Dog • currentState :: #sleeping, #waiting, #outside • bark • currentState := #waiting. • self changed: #bark • door: aDoor • door := aDoor. • door addDependent: self
Dog • goOut • currentState := #outside. • door removeDependent: self. • self changed: #move
Dog • update: aSymbol • (currentState == #waiting) & (aSymbol == #open) • ifTrue: [self goOut ]
Person • dog: aDog • dog := aDog. • dog addDependent: self
Person • update: aSymbol • aSymbol == #bark • ifTrue: [door open]. • aSymbol == #move • ifTrue: [door close]
Watcher • instance variable: name <String> • update: aSymbol • Transcript show: subjectName; show: ' '; show: aSymbol; cr • name: aString • name := aString
| person door dog | • door := Door new close. • door addDependent: • (Watcher new name: 'door'). • dog := Dog new. • door addDependent: dog. • dog addDependent: • (Watcher new name: 'Fido'). • person := Person new. • person door: door; dog: dog. • dog bark.
Improvements • Creating method • (have class method return initialized object) • Compose method • (Watcher on: door name: 'door') • (door watcherNamed: 'door')
Model and Memory Management • Dog allInstances • reports a lot of dogs! Garbage collection doesn't help. • Object uses a global dictionary to store dependents. Subject must "release" its observers/dependents.
Make Dog a subclass of Model • Model uses an instance variable to store dependents. It does not have to release its observers. • Subclasses of Model cause less problems with garbage collection. • Class that has dependents should be subclass of Model.
If you are not using Model then after the script says • dog bark. • add the messages • dog release. • door release. • person release
Advantage of Observer Pattern • Easy to add new observers. • Coupling between observer and subject is abstract.
Disadvantage of Observer Pattern • Often hard to understand relationships between objects in system. • Sometimes inefficient.
Adding New Observer • Suppose room also has a bird, which is usually in a cage. • If bird is not in cage and door opens, bird flies out.
Bird • update: aSymbol • (aSymbol == #open) & • (self isCaged not) • ifTrue: [self flyOut] • Script must now create a bird and make it depend on the door.
Summary • Observer is an important pattern • Used in a UI to make reusable components • Reduces coupling by increasing abstraction • Abstraction makes programs easier to change, harder to understand • Often requires a “script” to set up dependencies