Observer pattern: observe attributes independently



I would like to ask how I should correctly implement observer pattern when I need to achieve something like this:

WeatherStation[temperature, humidity ...]

and I need to be able to “observe” each attribute independently. So when temperature changes only temperature observers will be notified, when humidity changes only humidity subscribers will be notified.

My idea was that I would create some classes like ObservableTemperature and interface TemperatureObserver but I this way I would have to create two “classes” for each attribute.

Second option is to create only two interfaces for each attribute (something like TemperatureSource, TemperatureObserver …) and then implement the xxxSource interface in WeatherStation class but this way it is not reusable and I would need to have in WeatherStation class a lot of arrays (same number as “observable” attributes) keeping track of observers.

Is there any better option?

EDITED: Also it can also happen that I would have something like Display class which would subscribe to multiple attributes(not all) and still need to distinguish which one of them was updated.

Answer

Combining temperature, humidity, etc. into a class WeatherStation defines one domain concept. In terms of the Observer pattern, this is one subject. On the other hand, sending notifications consisting of single values would divide WeatherStation into multiple domain concepts and multiple subjects. Clearly there is a conflict between these two design decisions.

The GoF pattern is defined in terms of objects (not fields) as subjects. But note this does not restrict a subject from notifying different observers at different times. The pertinent section of the book begins on page 298.

Specifying modifications of interest explicitly. You can improve update efficiency by extending the subject’s registration interface to allow registering observers only for specific events of interest. When such an event occurs, the subject informs only those observers that have registered interest in that event. One way to support this uses the notion of aspects for Subject objects. To register interest in particular events, observers are attached to their subjects using

void Subject::Attach(Observer*, Aspects interest);

where interest specifies the event of interest. At notification time, the subject supplies the changed aspect to its observers as a parameter to the Update operation. For example:

void Observer::Update(Subject*, Aspect& interest);

This approach enables different observers to register for different notifications from one Subject. Note that regardless of which aspect(s) an observer registers for, it receives the same Subject in the notification message. It is up to the observer to read the necessary field(s) from the Subject.



Source: stackoverflow