Обход дерева с вызовом действий в узлах

237
14 ноября 2017, 23:05

У меня есть дерево, узлы которого имеют тип Node. В зависимости от типа (одной из реализаций Node) узлы различаются набором информации, которая в них хранится. У меня также есть действия Action, которые должны вызываться при посещении определенного типа узла. Действия каким-то образом регистрируются, затем происходит проход по дереву.

Пример действия:

public final class ActionA extends Action {
    @Override
    public void act(final NodeA node) {
        System.out.println("Act action1 (" + node.value() + ")");
    }
    @Override
    public void act(final NodeB node) {
        System.out.println("Act action1 (" + node.value() + ")");
    }
}

Код этих методов должен выполниться, при посещении узлов типа NodeA и NodeB. Помогите реализовать или расскажите как лучше это реализовать с точки зрения архитектуры.

Answer 1

С использованием паттерна Visitor:

class Node {
    protected final Node[] childs;
    public Node() {
        this(new Node[] {});
    }
    public Node(final Node[] childs) {
        this.childs = childs;
    }
    public Node[] childs() {
        return this.childs;
    }
    public void accept(final Action visitor) {
        for (final Node child : childs()) {
            child.accept(visitor);
        }
        visitor.act(this);
    }
}
interface Action {
    default void act(final Node node) {
        if (node instanceof NodeA) {
            this.act((NodeA) node);
        } else if (node instanceof NodeB) {
            this.act((NodeB) node);
        }
        else if (node instanceof NodeC) {
            this.act((NodeC) node);
        } else if (node instanceof NodeD) {
            this.act((NodeD) node);
        }
    }
    default void act(final NodeB node) {}
    default void act(final NodeA node) {}
    default void act(final NodeC node) {}
    default void act(final NodeD node) {}
}
class NodeA extends Node {
    public NodeA(final Node[] elements) {
        super(elements);
    }
}
class NodeB extends Node {}
class NodeC extends Node {}
class NodeD extends Node {}
class ActionA implements Action {
    @Override
    public void act(final NodeB node) {
        System.out.println("Action A / Node B");
    }
    @Override
    public void act(final NodeA node) {
        System.out.println("Action A / Node A");
    }
}
class ActionB implements Action {
    @Override
    public void act(final NodeC node) {
        System.out.println("Action B / Node C");
    }
    @Override
    public void act(final NodeD node) {
        System.out.println("Action B / Node D");
    }
}
public class ApplicationDemo {
    public static void main(final String[] args) {
        final Node node = new NodeA(new Node[]{
                new NodeB(), new NodeD(),
                new NodeB(), new NodeC()
        });
        node.accept(new ActionB());
        node.accept(new ActionA());
    }
}

Результат:

Action B / Node D
Action B / Node C
Action A / Node B
Action A / Node B
Action A / Node A
READ ALSO
Шаблон-одиночка и многопоточность в Java

Шаблон-одиночка и многопоточность в Java

Существует клиент-серверное приложения, на серверной(мультипотоковой) части я пытаюсь реализовать синглтон:

235
построение dom из inputstream

построение dom из inputstream

мне надо получить dom документа , который я получаю в виде inputStream есть ли такая возможность ? пробовал

227
Json не возвращает null поле

Json не возвращает null поле

Есть поле String, которое может быть nullИ вот если оно null, то в ответе в json этот null не показывается

228