2013-06-04 3 views
2

Как реорганизовать следующий код:Refactor рекурсивные модификации дерева

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); 
    } 
} 

Методы rAction1() и rAction2() выглядит очень похоже. Есть ли способ не повторять код в этом случае?

ответ

3

Вы можете использовать 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()); 
    } 
} 
1

Вы можете превратить action1 и action2 в объекты:

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() 
    } 
} 

Тогда вы можете написать один рекурсивный метод:

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

Для более общая версия этой идеи, посмотрите на visitor pattern.

+0

Примерно тот же ответ, что и у меня, но вы правильно сказали, что это шаблон посетителя :) –

+0

@ AleksanderBlomskøld - В самом деле, примерно такой же ответ. Вы были быстрее об этом, так что +1 к вам. :) Я думаю, что командный шаблон также вполне подходит для этого. –

+0

Это так просто. Спасибо вам обоим! – WojciechKo