|
|
|
What is double dispatch? This old technique doesn't get the exposure it deserves. Here, Kirk Pepperdine explains how it operates and where it is used, with examples.Published April 2004, Author Kirk Pepperdine
Page 1 of 2
next page: Double Dispatch With Commands
One of the beautiful things about object orientation (OO) is the notion that system behavior doesn't have to occur in a single object. Instead it should happen in the interactions between objects. What an object brought to the table was a number of methods that perform small primitive units of work. To get useful behavior, one had to group together other objects (or actors) that also contained methods that on their own didn't seem to achieve much. The power of this is that these small units of work could be reused in a variety of situations. The situations are to be driven by a more powerful actor or directory that would bring all of the pieces together and drive the interactions required to create the desired outcome. Done poorly and it's like watching the dance floor at the high school prom. Done well and you have a perfectly choreographed dance.
One of the patterns that is helpful in maintaining the desired level of separation between the actors is
the double dispatch. If you've not heard of this pattern, then don't despair because you're not alone. The
double dispatch has been forgotten, misunderstood, or just not recognized. Strangely enough, there is a
perfect example of it in the JDK. As much as I may gripe about the anti-patterns that do exist in the JDK,
I need to be fair and point out the good ones. In this case, the double dispatch pattern is well illustrated
by the Serializable
interface.
It may come as a surprise that a simple methodless interface can support a design pattern but that is exactly
what Serialiable
does. The question is, how is it a double dispatch? Interesting question given that most of
the code to support the design is hidden from the developer, but as we will see that is the beauty of this pattern.
It allows you to make a decision and implement useful functionality without having to know about rest of the
application.
If we take any object (lets call it A
) that implements Serializable
,
we can pass that object to another class
that knows how to serialize the object. For example, we could write the object to an ObjectOutputStream
as
demonstrated in listing 1. The developer(s) who wrote ObjectOutputStream
certainly have no knowledge
of my mythical object A
. What they do know is that it can be serialized because we said so. This point is
not really core to double dispatch but it does take care of the typing issue.
Listing 1: Sample Serialization
|
In order to serialize A
, ObjectOutputStream
first looks to see if the method
writeObject( ObjectOutputStream oos)
exists. If it does, then it calls that method with itself as an argument. The writeObject
method then dispatches
the call back to the ObjectOutputStream
(thus making this a double dispatch). In making this very simple call back,
ObjectOutputStream
has said: "I'm delegating back to you the responsibility of writing your state onto this stream".
In making that simple choice, ObjectOutputStream
has decoupled itself from our object
A
. Object A
in turn says ok,
here is some state that I want written on the stream. If the value is a primitive, then it can be dealt by the
overloading of the write method. If not, the back and forth can continue at the next level down in the objects
graph until all of the useful state has been placed on the stream.
Why one may not recognize it as being a double dispatch is because, firstly, we can't see the implementation, and secondly,
the issue is confused because it works even without the addition of writeObject
method to our class.
In the later case, reflection takes the role of the call back.
The real question is where can we use this in our code. The simple answer is anywhere one might "serialize" an object (for example, creating an XML document). In each case, the holder of the serialized object may come back and ask that object to fill in the form with it's vital information. The good thing about this is that it helps decouple the XML from the object.
Page 1 of 2
next page: Double Dispatch With Commands