在这种情况下我应该使用什么样的设计?

What kind of design shall i use in this scenario?

我是设计软件的新手,我正在尝试构建一个类似结构的树。
我有一个像这样的空界面:

interface Node{
}

两个classes NodeANodeB实现了这个接口,并且都有一些特定的属性。除了这些是节点之外,它们没有任何共同点。

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 可以根据特定条件创建上述 classes 的实例。

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

Driver class:

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

构建树后,我打算使用访问者模式来检索一些属性并进行一些操作。

So at last, when i get a Node b, i want to access its attributes (of NodeA or NodeB), which i know cant be done as Polymorphism doesnt work that way.

我认为使用 instanceof 梯子和 type-casting 不是正确的解决方案。
很抱歉这个愚蠢的问题,但作为设计新手,我不知道下一步该做什么。

如何解决这一设计问题?任何人都可以为此分享一个小的设计结构,假设这个结构会变得更大并且有足够的不同节点。 [可能 Java Generics 在这里帮忙]

注意:改变上面的设计很好,但如果可能的话,一个小的示例代码是值得赞赏的。

此答案在很大程度上取决于您在本节中的操作:

So at last, when i get a Node b, i want to access its attributes (of NodeA or NodeB), which i know cant be done as Polymorphism doesnt work that way.

就我个人而言,我建议您使用 Strategy Pattern。这样做的目的是拥有一个通用方法,例如 visit(它可以驻留在您的 Node 界面中,或者甚至可以创建一个 IVisitable 界面(或类似的东西) . 此方法的目的是处理算法的 visit 方面。

所以本质上,您将委托访问节点时发生的事情。如果您需要做一些特定的事情,让这个方法将 visitor 作为方法参数可能是有意义的,这样您的访问者就可以对节点本身的内容进行操作。

正如您提到的,可以在此处使用访问者模式。

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