DoubleDispatch

Double dispatch using a variation on the visitor pattern. The example assumes a game setting where there is a need to handle collisions (and does not deal with detection), but there is nothing stopping you from applying it to other similar problems.

public abstract class Entity
{
    protected void collide(Asteroid entity) {}
    protected void collide(Ship entity) {}
    protected void collide(Missile entity) {}
    public abstract void reverseCollide(Entity entity);
}

public class Ship extends Entity
{
    protected void collide(Asteroid entity) 
    {
        // die
    }
    protected void collide(Missile entity) 
    {
        // die
    }
    public void reverseCollide(Entity entity) { entity.collide(this); }
}

public class Missile extends Entity
{
    protected void collide(Asteroid entity) 
    {
        // disappear
    }
    public void reverseCollide(Entity entity) { entity.collide(this); }
}

public class Asteroid extends Entity
{
    protected void collide(Missile entity) 
    {
        // destroy and spawn smaller asteroids
    }
    public void reverseCollide(Entity entity) { entity.collide(this); }
}

This way of handling collisions has a lot of benefits. Inside each collide method, you know the precise type of both the colliding objects. This means you can access their fields in a type safe manner, with no casting or instanceof. It keeps encapsulation because each collision is handled in both objects, making it possible for the specific entity to keep it's collision code and methods private and local to the class. Only one method (reverseCollide) is exposed to the outside world.

And when the collision detection decides that entity a and b collides, b.reverseCollide(a) should be called. Make sure both pairs (a, b) and (b, a) are called if there is a collision between a and b.

Generalizing

If you need to solve multiple double dispatch problems, or need to centralize the handling somewhere outside the classes, you should consider using the general visitor pattern, that puts the collide methods into a Visitor interface (and calls them visit ) and puts the reverseCollide method into a Visitable interface (and calls it accept ).

public abstract class EntityCollider extends EntityVisitor {}

public class ShipCollider extends EntityCollider
{
    private final Ship self;

    public ShipCollider(Ship self)
    {
        this.self = self;
    }

    public void visit(Asteroid entity)
    {
        // you know the drill
    }
}

The above private variable and public constructor is not required if you use an inner class, so you can keep most of the brevity without throwing away generality.