Tuesday, October 13, 2009

Patterns - 038: Behavioral Patterns ( Observer )



The Observer pattern is useful for designing a consistent communication model between a set of dependent objects and an object that they are dependent on.

This allows the dependent objects to have their state synchronized with the object that they are dependent on.

The set of dependent objects are referred to as observers and the object that they are dependent on is referred to as the subject.

In order to accomplish this, the Observer pattern suggests a publisher-subscriber model leading to a clear boundary between the set of Observer objects and the Subject object.

Whenever the subject undergoes a change in its state, it notifies all of its
registered observers.

An observer can register or subscribe with multiple subjects.

Whenever an observer does not wish to be notified any further, it unregistered itself with the subject.

For this mechanism to work:
  • The subject should provide an interface for registering and unregistering for change notifications.
  • One of the following two must be true:
  1. – In the pull model — The subject should provide an interface that enables observers to query the subject for the required state information to update their state.
  2. – In the push model — The subject should send the state information that the observers may be interested in.
  • Observers should provide an interface for receiving notifications from the subject.

(Figure 33.1)

From this class diagram it can be seen that:
  • All subjects are expected to provide implementation for an interface similar to the Observable interface.
  • All observers are expected to have an interface similar to the Observer interface.
Several variations can be thought of while applying the Observer pattern, leading to different types of subject-observers such as observers that are interested only in specific types of changes in the subject.


Example

Let us build a sales reporting application for the management of a store with multiple departments.

Upon selecting a department, two types of reports are to be displayed:
  • – Monthly report — A list of all transactions for the current month for the selected department.
  • – YTD sales chart — A chart showing the year-to-date sales for the selected department by month.
Whenever a different department is selected, both of the reports should be refreshed with the data for the currently selected department.

Let us define three classes with the stated functionality as in follwing Table


ClassRoleFunctionality

ReportManager

Subject

Displays the necessary UI for the user to select a department.
Maintains the user selected department in an instance variable.
MonthlyReportObserver
Displays the monthly report for the selected department.

YTDChart

Observer

Displays the YTD sales chart for the selected department.


Observable Interface and Its Implementer


(Figure 33.2 )

Observer Class Hierarchy

(Figure 33.4 )

Example Application: Class Association

(Figure 33.5)
ReportManager User Interface

(Figure 33.3)
Logical Flow

  1. Using the ReportManager user interface whenever a user selects a particular department and clicks on the OK button, the ReportManager undergoes a change in its internal state (i.e., the value of its instance variable department changes).
  2. As soon as the new state is set, the ReportManager invokes the refreshData(Observable) method on both the curr ently registered MonthlyReport and the YTDChart objects.
  3. As part of refreshData method, both the report objects:a. Check to make sure that the subject that invoked the refreshData method is in fact the same Subject instance they have registered with. This is to prevent the observers from responding to unintended calls.b. Query the ReportManager for its current state using the getDepartment method.c. Retrieve appropriate data from the data file for display.

No comments:

Post a Comment