3

How can I refactor the following code:

class ModifyTree{
    public void doActionsOnTree(Tree tree) {
        rAction1(tree.getRoot());
        rAction2(tree.getRoot());
    }

    private void action1(Node node) {
        // do something with node;
    }

    private void action2 (Node node) {
        // do something with node
    }

    private void rAction1(Node node) {
        action1(node);
        for(Node nodeIterator : node.getChildren())
            rAction1(nodeIterator);
    }

    private void rAction2(Node node) {
        action2(node);
        for(Node nodeIterator : node.getChildren())
            rAction2(nodeIterator);
    }
}

Methods rAction1() and rAction2() looks very similarly. Is there a way to don't repeat the code in this case?

WojciechKo
  • 1,511
  • 18
  • 35

2 Answers2

3

You could use the Visitior pattern:

interface NodeHandler {
    public void handleNode(Node node);
}

class ModifyTree{
    private void handleNodeAndChildren(NodeHandler nodeHandler, Node node) {
        nodeHandler.handleNode(node);
        for(Node child : node.getChildren()) 
            handleNodeAndChildren(nodeHandler, child);
        }
    }

    public void doActionsOnTree(Tree tree) {
        handleNodeAndChildren(new NodeHandler() { public void handlNode(Node n) {/* code for raction1 goes here*/}}, tree.getRoot());
        handleNodeAndChildren(new NodeHandler() { public void handlNode(Node n) {/* code for raction2 goes here*/}}, tree.getRoot());
    }
}
Aleksander Blomskøld
  • 18,374
  • 9
  • 76
  • 82
1

You can turn action1 and action2 into objects:

interface Action {
    void doAction(Node node);
}
Action action1 = new Action() {
    @Override
    public void doAction(Node node) {
        // what used to be the body of action1()
    }
}
Action action2 = new Action() {
    @Override
    public void doAction(Node node) {
        // what used to be the body of action2()
    }
}

Then you can write a single recursive method:

private void rAction(Action action, Node node) {
    action.doAction(node);
    for (Node child : node.getChildren()) {
        rAction(action, child);
    }
}

For a more general version of this idea, take a look at the visitor pattern.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • About the same answer as me, but you correctly said that this is the visitor pattern :) – Aleksander Blomskøld Jun 04 '13 at 17:50
  • @AleksanderBlomskøld - Indeed, about the same answer. You were quicker about it, though, so +1 to you. :) I think the command pattern is also quite appropriate for this. – Ted Hopp Jun 04 '13 at 17:53