views:

34

answers:

1

I am trying to decide which is the better way to dispatch on a type in AspectJ. Suppose I am performing a computation on a tree with three kinds of nodes. I could then write a simple Java method:

private void computation(TreeNode node) {
    if (node instanceof Node0) {
        // Do stuff.
    } else 
    if (node instanceof Node0) {
        // Do stuff.
    } else 
    if (node instanceof Node0) {
        // Do stuff.
    }
}

or

private void computation(TreeNode node) {
    switch (node.kindNode()) {
        case NODE0:
            // Do stuff.
            break;
        case NODE1:
            // Do stuff.
            break;
        case NODE2:
            // Do stuff.
            break;
    }
}

or I could inject a method into each node type:

private void Node.computation() {
    throw new UnsupportedOperationException(getClass() + ".computation()");
}

private void Node0.computation() {
    // Do stuff.
}

private void Node1.computation() {
    // Do stuff.
}

private void Node2.computation() {
    // Do stuff.
}

Which method is preferable and why?

+1  A: 

what is preferrable very much depends on the situation.

If I understood your problem correct, you want somehow to add this "computation" method after-the-fact into an already existing type hierarchy, and changing the original types's source code isn't an option, right?

In this case, the most important question is: how frequent are changes to the Node type hierarchy? Because any such change will probably force you to adjust your aspect, which is a maintainance problem.

Having said that -- your third proposal is the "cannonical" object oriented solution. In general programming, it is usally preferred over the switch-case approach, because the latter tends to lead to complicated and difficult to understand code, unless the operations in computation() are very short and simple. Basically, the same holds true for an AspectJ based solution, as in your case. But it is slightly more difficult to set up the aspect, because it has to inject definitions in multiple subclasses, whereas in the other case, when you go for the switch-case solution, you would just inject a small forwarding method into the base class and jump from there into a plain java class holding your switch-on-type.

visitor pattern: actually, what you do here looks like the classical use case for the visitor pattern, which can be implemented elegantly using an aspect. Probably that would be the cleanest solution, but the visitor pattern in itself is an advanced topic (I can explain in more detail if there is interest)

Ichthyo

related questions