observable |
The Observer pattern decouples the responsibility of an
object to send change notification to its dependents and to update them
automatically. The os_observable class implements
the Observer pattern. It represents an observable object which can have one or
more observers. An observer can be any class object which can register a
callback function with the observable object. When an observable object
changes, an application calling notify_observers()
method on the observable, will cause all of its observers to be notified of
the change by a call to the callback function registered by the observers. The
order in which the observers are notified is unspecified. The observer object
does not have to inherit from any specific class in order to become an
observer.
To add observers to an observable object, use add_observer()
method on the observable passing a pointer to the observer and a pointer to
the observer's callback function as arguments. The callback function
must take a pointer to the observable as an argument and return void
. Conversely, remove any observer by using remove_observer()
method on the observable passing a pointer to the observer as an
argument. Finally, to notify the observers of changes to the observable
object, use notify_observers().
Use of member template feature in the add, remove, and notify observer methods
gives the flexibility of not having the observer and observable classes to
inherit from a specific interface class.
In the following example, the class os_weather
is the observable, and the classes os_fahrenheit_window
and os_celsius_window are the observers. The os_fahrenheit_window
displays the weather in fahrenheit format and the os_celsius_window
displays the same weather in the celsius format. The constructors of os_fahrenheit_window
and os_celsius_window objects, register their
change notification callback function update()
with the os_weather observable object. When a
change is made to the temperature of the os_weather
observable object it calls the notify_observers()
method to inform all the registered window objects of the change by calling
their update() methods.
#include <iostream>
#include <ospace/framework.h>
// Observable.
class os_weather
{
public:
os_weather() :
temperature_( 32 ),
observable_( this )
{
}
void temperature( int new_value )
{
temperature_ = new_value;
// Notify observers when the temperature changes.
observable_.notify_observers( this );
}
int temperature() const
{
return temperature_;
}
os_observable< os_weather >& observable()
{
return observable_;
}
private:
int temperature_; // in Fahrenheit.
os_observable< os_weather > observable_;
};
// Observer.
class os_fahrenheit_window
{
public:
os_fahrenheit_window( os_weather& weather ) :
weather_( weather )
{
// Register the observer.
weather_.observable().add_observer( this, &os_fahrenheit_window::update );
// Alternate syntax.
// weather_.observable().template add_observer<os_fahrenheit_window>(
// this, &os_fahrenheit_window::update );
}
~os_fahrenheit_window()
{
// Unregister the observer.
weather_.observable().remove_observer( this );
// Alternate syntax.
// weather_.observable().template remove_observer<os_fahrenheit_window>(
// this );
}
void update( os_weather* weather )
{
// Called by observable whenever notify_observers() is invoked.
// weather_ and weather should be the same object.
cout << "Temperature in Fahrenheit = " << weather_.temperature() << endl;
};
private:
os_weather& weather_;
};
// Observer.
class os_celsius_window
{
public:
os_celsius_window( os_weather& weather ) :
weather_( weather )
{
// Register the observer.
weather_.observable().add_observer( this, &os_celsius_window::update );
// Alternate syntax.
// weather_.observable().template add_observer<os_celsius_window>(
// this, &os_celsius_window::update );
}
~os_celsius_window()
{
// Unregister the observer.
weather_.observable().remove_observer( this );
// Alternate syntax.
// weather_.observable().template remove_observer<os_celsius_window>(
// this );
}
void update( os_weather* weather )
{
// Called by observable whenever notify_observers() is invoked.
// weather_ and weather should be the same object.
cout << "Temperature in Celsius = "
<< ((weather_.temperature() - 32) * 5) / 9 << endl;
};
private:
os_weather& weather_;
};
int
main()
{
os_weather weather;
os_fahrenheit_window fwin( weather );
os_celsius_window cwin( weather );
cout << "\n====Temperature changed====" << endl;
weather.temperature( 40 );
cout << "\n====Temperature changed====" << endl;
weather.temperature( 50 );
return 0;
}
====Temperature changed====
Temperature in Fahrenheit = 40
Temperature in Celsius = 4
====Temperature changed====
Temperature in Fahrenheit = 50
Temperature in Celsius = 10
Copyright©1994-2026 Recursion
Software LLC
All Rights Reserved - For use by licensed users only.