Title: Design Patterns
1Design Patterns
2Observer 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.
3Observer Pattern
observer/ dependent
Subject addDependent removeDependent changed
Observer update
model
ValueHolder value value
TextView update
4Observer Pattern
- Registration
- subject addDependent observer
- Notification
- self changed. self changed value
- Update
- define update aSymbol
5Notification
- Object notifies dependents when information
changes by sending itself a changed message. - changed anArg
- self dependents
- do each each update anArg
6Problem
- 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.
7Basic classes
- Dog
- bark / move
- Person
- Door
- open / close / isOpen
Object addDependent changed update
8Collaborations
Dog bark
watch
listen
Person
Door openclose
9Dynamic 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
10A Script
- person door dog
- door Door new close.
- dog Dog new.
- dog door door.
- person Person new.
- person door door dog dog.
- dog bark.
11Door
- opened ltBooleangt
- open
- opened true.
- self changed open
12Door
- close
- opened false.
- self changed close
- isOpen
- opened
13Dog
- currentState sleeping, waiting, outside
- bark
- currentState waiting.
- self changed bark
- door aDoor
- door aDoor.
- door addDependent self
14Dog
- goOut
- currentState outside.
- door removeDependent self.
- self changed move
15Dog
- update aSymbol
- (currentState waiting) (aSymbol open)
- ifTrue self goOut
16Person
- dog aDog
- dog aDog.
- dog addDependent self
17Person
- update aSymbol
- aSymbol bark
- ifTrue door open.
- aSymbol move
- ifTrue door close
18Watcher
- instance variable name ltStringgt
- update aSymbol
- Transcript show subjectName show ' ' show
aSymbol cr - name aString
- name aString
19- 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.
20Improvements
- Creating method
- (have class method return initialized object)
- Compose method
- (Watcher on door name 'door')
- (door watcherNamed 'door')
21Model 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.
22Make 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.
23-
- If you are not using Model then after the script
says - dog bark.
- add the messages
- dog release.
- door release.
- person release
24Advantage of Observer Pattern
- Easy to add new observers.
- Coupling between observer and subject is abstract.
25Disadvantage of Observer Pattern
- Often hard to understand relationships between
objects in system. - Sometimes inefficient.
26Adding 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.
27Bird
- update aSymbol
- (aSymbol open)
- (self isCaged not)
- ifTrue self flyOut
- Script must now create a bird and make it depend
on the door.
28Summary
- 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
29Creational Patterns
- Factory Method
- Factory Object
- Abstract Factory
- Builder
- Prototype
- Singleton
30Abstract Factory
- Sometimes a group of products are related -- if
you change one, you might need to change them
all. - Solution
- Make a single object that can make any of the
products.
WidgitFactory CreateScrollBar CreateWindow
ScrollBar
MotifScrollBar
PMScrollBar
MotifWidgetFactory CreateScrollBar CreateWindow
PMWidgetFactory CreateScrollBar CreateWindow
31Making Abstract Factory
- Give Producer a component called Factory
- Create class Factory
- Add instance variable factory to Producer
- Change constructor to have line factoryFactory
new - Move factory methods to Factory
- Copy factory method to Factory
- Change sends of createFoo to factory createFoo
32Refactoring creation
- Encapsulate in a method makeProduct
- (Factory method)
- Groups of related products gt move factory
methods to a new object - (Abstract Factory)
- Method too big gt method object / Builder
- User customizable gt Prototype
33- Prototype not used much in Smalltalk use
classes as objects instead. - Builder often used only to encapsulate building,
not provide variation. (No subclassing) - Factory method very common in Smalltalk less
common in Java. Instead, use Dependency
Injection.
34Dependency Injection
- Eliminate dependencies between classes by
- creating settors for objects, instead of creating
them in a constructor - describing the dependencies between classes with
a script and - having a standard module read the script, create
the objects, and inject the dependencies.
35The script
- Smalltalkers often use code
- Smalltalk literal
- XML
- Non-standard format
36- windowSpec
- "UIPainter new openOnClass self andSelector
windowSpec" - ltresource canvasgt
- (FullSpec
- window
- (WindowSpec label 'Payroll' bounds
(Rectangle 1245 452 1544 761 ) ) - ...
37WikiWorks configuration file
- Server
- port80
- directory.nameWiki's Home at UIUC
- accessLogaccess.log
- statusLogstatus.log
- Wiki
- nameCampSmalltalk
- directoryCampSmalltalk
- Wiki
- nameVisualWorks
- directoryVisualWorks
38Dependency injection
- Makes components more composable
- Harder to debug a component
- Cant see relationship between components in the
browser - Requires reflection in the programming language
39Design patterns and refactoring
- Patterns are most useful for complex systems.
- Add them later by refactoring
- Keep system simple no unnecessary patterns
- Keep system flexible all needed patterns