10

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.

5
  • The questions in the body don't really seem to match your title. Which is really the core of the question?
    – Nicole
    Commented Dec 17, 2011 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
    Commented Dec 17, 2011 at 1:28
  • @Renesis: Here is a forum thread asking a similar question to mine: gamedev.net/topic/497105-observer-pattern
    – User
    Commented Dec 18, 2011 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
    Commented Dec 19, 2011 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
    Commented Dec 20, 2011 at 18:16

3 Answers 3

4

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

4
  • 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
    Commented Dec 16, 2011 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
    Commented Dec 16, 2011 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
    Commented Dec 16, 2011 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
    Commented Dec 19, 2011 at 7:18
1

There are a few ways to send a "Java Like" generic event argument in C++.

1) Declare the event argument as void * and cast it to the right class in the event handler.

2) Declare the event argument as a pointer/ref to a new class/interface such as ( in response to your example )

class GenericEventArgument
{
  virtual bool didAction1Happen() = 0;
  virtual int getActionInteger() = 0;
};

And have the actual event argument classes derive from this class.

As for you question regarding a template based observer check out

http://www.codeproject.com/Articles/3267/Implementing-a-Subject-Observer-pattern-with-templ

-1

I don't know whether this is the canonical name, but from my old Smalltalk days I remember the term "aspect" to identify what has changed on the observable.

It's not as complex as your idea of EventArg (and subclassing it); it just passes a string (could even be an integer constant) from the observable to the observer.

Plus: There are just two simple methods (update(observable) and updateAspect(observable, aspect)

Minus: The observer may have to ask the observable for further information (i.e., your "integer number")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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