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.

Example <ospace/framework/examples/observable1.cpp>
#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.