【问题标题】:What kind of design shall i use in this scenario?在这种情况下我应该使用什么样的设计?
【发布时间】:2020-02-28 08:08:51
【问题描述】:

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

interface Node{
}

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,它根据特定条件创建上述类的实例。

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,我想访问它的属性( NodeANodeB),我知道这不能完成,因为多态性没有 那样工作。

我认为使用 instanceof 阶梯和类型转换不是正确的解决方案。
抱歉这个愚蠢的问题,但是对于设计来说是新手,我不知道下一步该做什么。

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

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

【问题讨论】:

标签: java design-patterns software-design


【解决方案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;
        }
    };

然后调用accept:

Node node = ...;
Integer result = node.accept(visitor);

【讨论】:

    【解决方案2】:

    这个答案很大程度上取决于您在本节中所做的事情:

    所以最后,当我得到一个节点 b 时,我想访问它的属性(的 NodeA 或 NodeB),我知道这不能完成,因为多态性不起作用 那样。

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

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

    【讨论】:

      猜你喜欢
      • 2022-12-17
      • 1970-01-01
      • 2015-12-02
      • 2018-11-11
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多