Never confuse education with intelligence, you can have a PhD and still be an idiot.
- Richard Feynman -



Design patterns - Observer

From Juneday education
Revision as of 18:07, 30 November 2016 by Rikard (Talk | contribs) (Further reading: removed TODO tag)

Jump to: navigation, search

Description

In this chapter, we'll discuss the Observer pattern.

Aim of the pattern

The intent of this pattern is to allow for a one-to-many relationship between one object with important state, and many interested objects, subscribing to changes in the important object. It is often described in terms of a "Subject" object which is observable by many "Observers" (or sometimes "Listeners").

Problem description

We often have a situation where something central (the Subject) in our application changes its state, and many components (observers) would be interested to hear about this. The Subject should be loosely coupled with any amount of observers and treat them uniformly. But the actual observers can be totally unrelated objects of very different classes.

class SuperImportantClass{
  List interestedObjects; // what type should we use here?
  // how do we populate the list with interested objects?

  // Times they are a changing...(but Robert stays the same)
  void stateChangesForSomeReason(){
    for(Object o : interestedObjects){
      //tell them about the changes, but how?
    }
  }
}

As usual, we don't want our classes to know too much about each other, so that things stay on a high abstraction level and things can vary and change without too much impact between classes.

Solution - applying the Observer Pattern

The solution to this problem is to follow the Observer pattern. As usual, there are a few variations of this pattern but we'll explain a common design for it. In order to keep the classes (Subject and Observers) loosely couples (knowing little about each others implementation details), we define two interfaces. We're gonna call the interface for the Subject Observable and the interface for the observers Observer. The Observable interface declares methods every Subject object must have:

  • public void add(Observer o); // an observer wants to register
  • public void delete(Observer o); // unregister observer
  • public void notifyObservers(); // notify all observers

The Observer interface declares (perhaps, but at least in our version) only one method:

  • public void update(Observable o); // this will be called when the Subject wants you to be notified

By using interfaces, we can keep the Subject in happy ignorance about the observers, as well as every observer happily ignorant about the details about the Subject they are observing. We obtain a loose coupling between the actual concrete classes. As long as the Subject adheres to the specification of the Observable interface, and as long as all the observers adhere to the specification of the Observer interface, they can "talk" to each other without knowing too much about the details.

Disclaimer: Note, that in our examples, actually, the observers are kind of coupled with the Observable (they know exactly what class it is made from, and even down-cast the Observable to that type!), so this feature isn't bilateral in our examples. But at least, you can see that the Observable Subject isn't aware of the classes and types of its observers other than that they are adhering to the Observer interface.

Another example

TODO:

/* TODO: some example code */
/* TODO: some example code */

Exercises

Task 1 - TODO: write an exercise, man!

/* TODO: some source code here */

Challenge - 1

TODO: Challenge 1

Challenge - 2

TODO: Challenge 2

Hints

TODO: If necessary, create hints for the exercise.

Suggested solutions

Expand using link to the right to see the full content.

You can download source code including suggested solutions TODO: here (github). But here are the source code for the suggested solutions:

/* TODO: suggested solution sources */

Chapter links

Vimeo channel

Source code

  • Github [TODO: repository]

Books this chapter is a part of

Further reading

Note: the articles above use slightly different designs. And their designs vary slightly compared to our version, but the general idea is the same.

Book TOC | previous chapter | TODO: next