Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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.

share|improve this question
    
The questions in the body don't really seem to match your title. Which is really the core of the question? –  NickC Dec 17 '11 at 1:01
    
@Renesis: I'm currently using the Observer pattern as in the code sample at the beginning of my post. For the code I'm currently working on, it turns out I need to know specifically what changed so I can react accordingly. My current implementation of the observer pattern (which is the standard one) doesn't provide this information. My question is how to best get information about what changed. –  User Dec 17 '11 at 1:28
    
@Renesis: Here is a forum thread asking a similar question to mine: gamedev.net/topic/497105-observer-pattern –  User Dec 18 '11 at 11:46
    
Ad update2: I definitely support using Boost.Signals. It's a lot more convenient than rolling your own. There is also libsigc++ if you wanted something lighter-weight just for this task (Boost.Signals uses a lot of code from the rest of Boost); it is not thread-safe though. –  Jan Hudec Dec 19 '11 at 8:21
    
Regarding speed issues: I don't know specifically how speedy Boost.Signals is, but that's only a concern when you have a huge amount of events flying around... –  Max Dec 20 '11 at 18:16

1 Answer 1

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

share|improve this answer
5  
If the observer interprets the argument, there is a coupling, no matter how you hide the type. In fact I'd say it's more difficult to evolve if you pass Object (void *, boost::any or something similarly generic) than if you pass specific type, because with the specific type you'll see at compile time that something changed, while with the generic type it will compile and stop working, because the observer will not be able to work with the actual data passed. –  Jan Hudec Dec 16 '11 at 7:21
    
@JanHudec: I agree with that, but does that mean you make a specific one-off Observer/Subject subclass set for each argument (i.e., for each use case)? –  User Dec 16 '11 at 14:55
    
@JanHudec: also the coupling is only one way. The subject has no idea about the observers. Yes the observer knows about the subject but isn't that the way observer pattern works? –  User Dec 16 '11 at 15:25
1  
@User: Yes, I make a specific interface for each subject and each observer implements the interfaces of the subjects it needs to observe. Well, all languages I use have bound method pointers in the language or framework (C# delegates, C++11 std::function Boost boost::function, Gtk+ GClosure, python bound methods etc.), so I just define methods with appropriate signatures and ask the system to create the actual observer. The coupling is indeed just one way, the subject defines the interface for observers, but does not have idea about their implementation. –  Jan Hudec Dec 19 '11 at 7:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.