Double Dispatch Pattern

The Double Dispatch pattern is a design pattern used to leave a class hierarchy open to having extra operations added to it. Further, double dispatch allows the implementations of such added operations to be different according to the actual, or “concrete”, type of the class.

In this article I will start with an example of C# double dispatch. Although the example uses C# as its language, both Java double dispatch and C++ double dispatch could be implemented in a very similar way.

Example

Consider a drawing program (yes I know you’ve heard this one a thousand times before, but it serves well as an example!). This program will have a shape class hierarchy that will be headed up by an interface called IShape. Let’s say we have two concrete classes: Circle and Rectangle.

The role of the shape hierarchy is to encapsulate information about the properties of the shapes in our drawing program, such as their positions and sizes. That is to say, its role is to contain application logic, and it does not want to have code in it that interacts with the GUI. In typical GUI tradition, we will want to put up dialog boxes for each shape to allow the user to update its properties, and this dialog box will be different depending on whether the IShape object is a Rectangle or Circle. Here is a fragment (in C#) of the shape hierarchy:

    interface IShape
    {
        ...

        void move(int newX, int newY);

        ...

        void process(IProperties props);
    }

    class Circle : IShape
    {
        ...

        void IShape.move(int newX, int newY) { ... }

        ...

        void IShape.process(IProperties props)
        {
            props.show(this);
        }
    }

    class Rectangle : IShape
    {
        ...

        void IShape.move(int newX, int newY) { ... }

        ...

        void IShape.process(IProperties props)
        {
            props.show(this);
        }
    }

I have left in the move() method simply to give the hierarchy some sense of realism, but process() is the method we’re really interested in here. Code that uses our shape hierarchy will only be doing so through references to IShape. However, when methods are called, the methods invoked are those of the concrete classes – therefore, in method calls the actual concrete class is known.

Further, in the implementation of process() in a concrete class, the this reference has the type of the concrete class – this allows us to take advantage of overloading.

This brings me to the classes that will actually display the properties dialogs – i.e. the classes that will actually contain the GUI code. They will be headed up by an interface that I am going to call IProperties, and that looks like this:

    interface IProperties
    {
        void show(IShape s);
        void show(Circle c);
        void show(Rectangle r);
    }

IProperties declares a show() method overload for each class in the IShape hierarchy. Because (in the implementation of the process() method) this refers to the concrete class of the object in the IShape hierarchy, the correct overload of IProperties.show() will be called.

If the IProperties interface has only one implementation – i.e. presumably called Properties – then it is possible to get away without the interface. However, this is something I do not recommend as it makes IShape and its subclasses just a little to tightly coupled to its properties for comfort. Further, IProperties may have more than one concrete class. For example, imagine that our drawing program is quite sophisticated and can distinguish between regular users and administrator level users. Let’s say that administrators have extra properties available to them. This would require more than one implementation of IProperties – say, UserProperties and AdminProperties. Then all that is needed is for an instance of the correct concrete properties class to be passed to IShape.show(). To keep the article’s size down a bit, I haven’t shown any of the code for IProperties‘ concrete classes, but I assume readers will have no problem mentally filling these in.

Now, the following example code shows how an IShape object’s properties can be invoked:

    void example(IShape sh, IProperties props)
    {
        sh.process(props);
    }

The Double Dispatch Pattern

So far I’ve just given a code example – now to show double dispatch as a pattern. I’m going to do this using a very simple description.

  • We are doing object oriented software development using a language such as C#/Java/C++. We want to add methods to a class hierarchy [the shape hierarchy], but (a) we want to keep code for these operations decoupled from the hierarchy and/or (b) we want to avoid modification of the hierarchy’s own code. Further, we want these operations to be polymorphic – that is to say, we want each concrete (derived) class in the hierarchy to have its own implementation of the method servicing the operation.
  • Therefore… First, invoke the operation on an object in the hierarchy [that is, via the process() method, in the example], and let the object (which knows what its own concrete class is) forward the operation on to another “handler” object containing the method that services the operation [the IProperties object that has the show() method]. This solves the problem but at the expense of having more class hierarchies to manage and maintain. Also, if a class is added to the original hierarchy, then each handler object class will need a method adding to it

This is a standalone write-up of the double dispatch pattern – as opposed to the informal illustration given by the above example. In passing, I hope to add further examples in the (near) future.

Finally

While I’ve seen a few examples of the double dispatch pattern in text books, I haven’t seen any literature describing it as such, that is, as a pattern (but note I’m saying I haven’t seen any, not that there aren’t any). Normally, double dispatch is mentioned as a technique used within the Visitor pattern, a more specific design pattern (see Gamma et al – the “Gang of Four Book”, mentioned in my previous article A Brief Introduction to Software Patterns). In fact I think developers often confuse the Double Dispatch pattern with the Visitor pattern. I think that is a shame, and that the former needs to be understood in its own right.

1 Comment

Leave a Comment

Your email address will not be published. Required fields are marked *