I’m going to read through Head First Design Patterns from O’Reilly after it was recommended on an HN post that I read recently. After finishing a chapter, I’m going to write a quick recap of what I learned to help with retention.
First up is the Observer Pattern, which creates a one to many dependency between stateful objects (observables) and those that depend on state (observers).
How it works
Observables, sometimes called “Subjects”, implement a set of methods (often in an interface) for registering observers, removing observers, and notifying observers that state changes have occurred. The observable is in charge of keeping track of a list of observers that have registered for notifications. The notification method iterates through this list, sending notifications to all observers in the list.
Observers implement an interface that just contains one method: update. This update method is called when an observable changes state, and concrete observers can perform appropriate actions in response to the state change.
This pattern provides loose coupling between Observables and Observers: they can interact with each other through their interface methods and require no additional knowledge of concrete implementations on either side of the relationship to continue to interact. Because of this, changes to lists of observers / observables can change at runtime, and object implementations can change without affecting the other side of the relationship.
Push vs Pull state updates
There are two ways Observers can receive state changes from Observables: “push” and “pull”
When an Observable undergoes a state change, it can push its new state to observers as part of the notification process. Alternatively, an observable can just notify observers that state has changed without sending over any state, allowing observers to respond to the update notification by polling the observable for just the pieces of state with which they are concerned.
Push style notifications can lead to observers getting updates for state that is not relevant. Pull style notifications are therefore viewed as more “correct”, allowing observers to make their own decisions on which parts of the Observable’s state interest it. This also promotes loose coupling, since the observable can expand itself with additional exposed state and can just provide new getter methods that interested observers can use.
How Does it work in Java?
Java.util.Observer is an interface with an update method that Observables should implement and
Java.util.Observable is a Class. It’s kind of weird that Java.util.Observable is a class, but I guess they wanted to provide concrete implementations for methods to handle notifications and storing lists of observers.
The Observer class also offers a method
setChanged() that sets a boolean field in the class called “changed” to “true”. This gives the programmer more control over when update methods on observers should actually be called. Say your Observable was collecting very sensitive measurements, so state was changing constantly… you could set a threshold that only calls
setChanged() once the threshold has been reached, and only then would notifyObservers actually send notifications.
Both push and pull options are available for use in the Java Observable class, by either calling
notifyObservers() for pull style notifications, or
notifyObservers(Object arg) for push style (Object arg being a copy of the updated state)
Because Observable is a class, you need to subClass it to use it. The setChanged method is protected, so you can’t use it unless your class subClasses Observable. This means you can’t create an Observable instance object and use it in a “has-a” object composition relationship in another class because its methods won’t be accessible!
My next post will be about the Decorator pattern.