C/C++

Generalizing Observer

By Herb Sutter, September 01, 2003

The function facility, recently adopted by the C++ standards committee, provides a generalized way of working with arbitrary functions when all you know (or need to know) is their approximate signature. It turns out that this facility enables us to write, among other things, generalized implementations of important design patterns like Observer. Those generalized design patterns, in turn, motivate two small but important extensions to function itself.

The function facility, recently adopted by the C++ standards committee,
provides a generalized way of working with arbitrary functions when all you
know (or need to know) is their approximate signature. It turns out that this
facility enables us to write, among other things, generalized implementations
of important design patterns like Observer. Those generalized design patterns,
in turn, motivate two small but important extensions to function itself.
[Note: In both the two previous columns, I promised to talk about inline
in "the next column." Last time I put off inline in order to cover another
fun topic, namely private. This time I've again decided to put off inline
because I had so much to say about function in my current The New
C++ column [1] that it turned into two columns - one to describe function
itself (which was the topic of [1]), and one to describe a generalized Observer
implementation that uses function and motivates changes and extensions
to function (this article). I'm going to stop making promises about inline,
but I really do intend to treat it once I stop thinking of even more interesting
things to write about.]

In [1], I gave an overview of one of the first two extensions that were approved
in October 2002 for the standard library extensions technical report (the "Library
TR"): Doug Gregor's proposal for polymorphic function object wrappers. [2] This
function facility comes directly from the Boost project [3], an important
(and free) collection of C++ libraries available for you to download and try
out today.

In brief, the function facility provides a generalized way of working
with arbitrary functions when all you know (or need to know) is their signature.
In fact, as it turns out, you don't even need to know the target function's
exact signature - any target function with a compatible signature, meaning one
where the parameter and return types are appropriately convertible, will work
just fine. A function can bind to a nonmember function, a member function,
or a functor that defines its own operator() and can therefore be called
just like a function. (I'm going to use the term "functors" for the latter,
instead of the alternative "function objects," to avoid confusion with "function
objects" which means objects of the function library facility we're discussing.)

In this article, I'll focus on showing how function lets us simplify
and expand the classic Observer pattern. Along the way, I hope to persuade you
that Observer (and other patterns like it) compellingly demonstrates not only
the usefulness of function, but also why function itself should
be further generalized beyond its current state in the draft standard library
technical report.

Briefly, the Observer pattern "define[s] a one-to-many dependency between objects
so that when one object [the subject] changes state, all its dependents [its observers]
are notified and updated automatically." [4] Observer commonly arises in event-driven
systems, such as operating systems and GUI environments (e.g., Smalltalk's Model/View/Controller
framework), where objects or processes need to respond to state changes elsewhere
in the system (e.g., external input) without knowing in advance when they might
happen. Allowing such observers to idle and only respond to events as they occur
is almost always better than requiring them to perform constant polling, or busy-waiting,
just in case an event might have happened since the last time the observers looked
in on their subject.

As described in [4] in an object-oriented form, a Subject lets observers register
themselves for later callback. The observers inherit from a common base class,
and the subject keeps a list of base class pointers. Figure
1 shows the structure of this object-oriented form of Observer:

Figure 1: Observer pattern's structure, as it appeared in Design Patterns
[4]

The code might look something like the following Example 2 (adapting the example
in [4]). I've kept Subject's member functions as virtual for consistency
with [4], even though it's debatable whether or not that is a generally useful
choice.

Note that in this OO version of the pattern, Subjecthas two limitations:
First, it is hardwired to be observable only by an object of a type that inherits
from Observer. Second, the callback function itself has to have a prescribed
name and exact signature. Both of these limitations arise because Subject
stores its observers list using object pointers into a fixed hierarchy.

How can we remove these limitations? As a first step, we might think we could
alleviate the second limitation somewhat by storing a member function pointer,
which would theoretically allow the callback function to have any name, although
it would still have to have a fixed signature. There are several problems with
this approach: First, for the callback functions to be useful they must still
be predeclared as pure virtuals in the Observer base class, which means
that although the callback gains some name flexibility, it still has to be one
of a predefined set of special known names (reminiscent of Henry Ford's famous
quote, "you can have any color you want, as long as it's black"). Second, the
Subject would have to store the member function pointer not instead of,
but in addition to, the object pointer, so that it knows what object
to dispatch to.

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Video

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!