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:
- what's the C++ way to pass a generic argument (as Java does)?
- 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.