Какой дизайн я должен использовать в этом сценарии? - PullRequest
0 голосов
/ 28 февраля 2020

Я новичок в разработке программного обеспечения, и я пытаюсь построить Tree, как структура.
У меня есть пустой интерфейс, подобный этому:

interface Node{
}

Два класса NodeA и NodeB реализовать этот интерфейс, и оба имеют определенные атрибуты c. За исключением того, что это узлы, в них нет ничего общего.

class A implements Node {
    public String a;
    public A(String a){
       this.a = a;
    }
}

class B implements Node {
    public int a = 5;
    public String z = "xyz";

    public B(int a,String z){
         this.a = a;
         this.z = z;
    }
}

У меня есть class Parse, который создает экземпляры вышеуказанных классов в зависимости от определенных условий.

class Parse {
    List<Boolean> l;
    private static int i=0;
    Parse(List<Boolean> l){
        this.l = l;
    }

    private Node parseA() {
        return new A(/* param */); // Assume some parameters here
    }

    private Node parseB() {
        return new B(/* param */); // Assume some parameters here
    }

    private boolean getNextState(){
        return l.get(i++);
    }

    public Node parse(){
        boolean x = getNextState();
        if(x){
            return parseA();
        }
        else{
            return parseB();
        }
    }
}

Класс драйвера:

public class Test {
    public static void main(String[] args) {
        List<Boolean> l = Arrays.asList(true,false); // so on...
        Parse p = new Parse(l);
        Node b = p.parse();  // not sure if its NodeA or NodeB
    }
}

После построения дерева я планирую использовать шаблон посетителей для получения некоторых атрибутов и выполнения некоторых операций.

Итак, наконец, когда я получаю Node b, я хочу получить доступ к его атрибутам (NodeA или NodeB), что, как я знаю, не может быть сделано, так как полиморфизм не работает таким образом.

Я думаю, что использование instanceof лестниц и приведения типов не является правильным решением.
Извините за эту глупую проблему, но, будучи новичком в проектировании, я не понимаю, что делать дальше.

Как решить эту проблему? может ли кто-нибудь разделить небольшую структуру проекта для этого, предполагая, что эта структура будет расти больше и иметь множество различных узлов. [может быть Java Generics помогите здесь]

Примечание: изменение вышеуказанного дизайна - это хорошо, но, если возможно, приветствуется небольшой пример кода.

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

Как вы уже упоминали, здесь можно использовать шаблон посетителя.

interface Node {
    <T> T accept(NodeVisitor<T> visitor);
}

class A implements Node {
    public String a;
    public A(String a){
       this.a = a;
    }

    @Override
    public <T> T accept(NodeVisitor<T> visitor) {
        return visitor.visit(this);
    }
}

class B implements Node {
   public int a = 5;
   public String z = "xyz";

   public B(int a,String z){
        this.a = a;
        this.z = z;
    }

    @Override
    public <T> T accept(NodeVisitor<T> visitor) {
        return visitor.visit(this);
    }
}

interface NodeVisitor<T> {
    T visit(A node);
    T visit(B node);
}

Затем определите конкретную операцию, реализовав соответствующий посетитель:

    NodeVisitor<Integer> visitor = new NodeVisitor<Integer>() {
        @Override
        public Integer visit(A node) {
            // TODO do something with A node
            return null;
        }

        @Override
        public Integer visit(B node) {
            // TODO do something with B node
            return null;
        }
    };

и просто вызовите вызов:

Node node = ...;
Integer result = node.accept(visitor);
1 голос
/ 28 февраля 2020

Этот ответ во многом зависит от того, что вы делаете в этом разделе:

Итак, наконец, когда я получаю Узел b, я хочу получить доступ к его атрибутам (NodeA или NodeB), которые я Я знаю, что это невозможно сделать, так как полиморфизм не работает таким образом.

Лично я бы предложил вам использовать шаблон стратегии . Целью этого было бы иметь общий метод, скажем, visit (который может находиться в вашем интерфейсе Node, или, возможно, даже создать интерфейс IVisitable (или что-то в этом роде). Цель этого метода будет обрабатывать аспект вашего алгоритма visit .

Итак, по сути, вы бы делегировали , что происходит при посещении узла. Если вам нужно что-то сделать Например, c, возможно, имеет смысл использовать этот метод в качестве параметра метода visitor, чтобы ваш посетитель мог работать с содержимым самого узла.

...