C++ – Observer pattern; knowing *what* changed

cdesign-patternsobserver-pattern

I've created two abstract classes Subject and Observer that define a classic Observer pattern interface. I derive from them to implement the Observer pattern. An observer might look like this:

void MyClass::Update(Subject *subject)
{
    if(subject == myService_)
    {
        DoSomething();
    }
    else if(subject == myOtherService_)
    {
        DoSomethingElse();
    }
}

This is fine and it tells me who changed something. However, it doesn't tell me what changed. Sometimes this is ok because I'm just going to query the Subject for the latest data, but other times I need to know what exactly changed on the Subject. I notice in Java they have both a notifyObservers() method and a notifyObservers(Object arg) method to presumably specify details about what changed.

In my case I need to know if one of a couple different actions happened on the subject and, if it's a particular action, to know an integer number related to that action.

So my questions are:

  1. what's the C++ way to pass a generic argument (as Java does)?
  2. Is Observer even the best pattern? Perhaps some kind of event system?

UPDATE

I found this article which talks about templating the Observer pattern: Implementing a Subject/Observer pattern with templates. This made me wonder if you could template an argument.

I found this stack overflow question which talks about templating the argument: Template based Subject Observer pattern – Should I use static_cast or dynamic_cast. However, the OP seems to have a problem that no one has answered.

The other thing I could do is change the Update method to take an EventArg object as in:

void MyClass::Update(Subject *subject, EventArg arg)
{
  ...

And then create subclasses of the EventArg for specific argument data, and then I guess cast it back to the specific subclass within the update method.

UPDATE 2

Also found an article, On creating an asynchronous message-based c++ framework; part 2 which discusses having the Subject communicate details about what changed.

I'm now seriously considering using Boost.Signals. Using my own observer pattern made sense when it was simple, but templating the type and an argument is starting to get complicated. And I may need the thread safety of Boost.Signals2.

UPDATE 3

I also found some interesting articles on the observer pattern:

Generalizing Observer by Herb Sutter

Implementing the Observer Pattern in C++ – Part 1

Experiences of Implementing the Observer Design Pattern (Part 2)

Experiences of Implementing the Observer Design Pattern (Part 3)

However, I've switched my implementation to using Boost.Signals which, while possibly tad bloated for my purposes, is successfully working. And probably any concerns of bloat or speed are irrelevant.

Best Answer

Whether C++ or JAVA, a Notification to the observer can come along with the information of what is changed. The same methods notifyObservers(Object arg) can also be used in C++ as well.

Generally, the issue will remain is that there could be multiple subjects dispatching to one or multiple observers and hence, the class arg cannot be hard coded.

Usually, the best way to do is to make arg in the form of generic message/tokens that forms the same data type for various classes but values differ for different observed classes. Alternatively, if all such notification values are derived out of the class on some based class which is common to all.

For observer pattern, it is important that Arg data type is not hard coded between the observee and observer - else it is a coupling that makes things difficult to evolve.

EDIT
If you want that observer not only observes but also needs to do a lot of other tasks based on the what has changed then, you can also check out Visitor pattern. In visitor pattern, the observer/visitor calls the modified object and hence can not only know what the modification is but can actually work on it

Related Topic