我是设计软件的新手,我正在尝试构建类似struct的Tree。
我有一个空的界面,像这样:
interface Node{
}
两个类NodeA
和NodeB
实现了此接口,并且都具有一些特定的属性。除了这些是节点外,它们中没有任何共同点。
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
有帮助]
注意:更改上面的设计是可以的,但如果可能的话,建议您使用少量示例代码。
答案 0 :(得分:1)
此答案在很大程度上取决于您在本节中所做的事情:
因此,最后,当我得到一个节点b时,我想访问它的( NodeA或NodeB),我知道无法完成,因为多态性无法正常工作 这样。
我个人建议您使用Strategy Pattern。这样做的目的是要有一个通用的方法,例如visit
(可以驻留在您的Node
接口中,甚至可以创建一个IVisitable
接口(或类似的方法)该方法的目的是处理算法的 visit 方面。
因此,从本质上讲,您将委托访问该节点时会发生什么。如果您需要做一些特定的事情,让此方法接受visitor
作为方法参数可能很有意义,以便您的访问者可以对节点本身的内容进行操作。
答案 1 :(得分:1)
正如您所提到的,可以在此处使用“访客”模式。
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);