使用访问者模式在Java中实现toString方法?

时间:2011-10-21 08:09:41

标签: java visitor-pattern

以下是我的一些Java代码

public List<OBJ> a = new ArrayList<OBJ>();
public String A;
public String B;
public String C;
for (OBJ o : a) {
    // .... TODO
}

所以我有一个接口OBJ,有三个实现OBJ的对象,比如X,Y,Z。所以我将X / Y / Z对象存储在List a中。现在说我要通过循环,如果o是实例X存储X.value在A中,如果Y存储Y.value在B中,如果Z存储Z.value在C中。所以问题实在是怎么做你弄清楚用什么对象类型o(X,Y,Z)将它们的值存储在正确的字符串中。

注意:我想使用Visitor pattern或类似的东西,但我并没有真正掌握它,所以我会请求你的帮助。

这意味着没有实例或类型转换和无专用方法,如

interface OBJ {
    void blah();
}

class X implements OBJ {
    public void blah();
} // etc

谢谢!我真的想让软件工程的这个重要方面失败!

嘿哇谢谢你的详细而快速的回复,但我的情况有点复杂,对不起我之前没有添加过。

所以字符串A,B,C实际上存放在另一个类中,如

class ARGH {
    public List<OBJ> a = new ArrayList<OBJ>();
    public String A;
    public String B;
    public String C;
    //invisible constructor here
    public String toString () {
        for (OBJ o : a) {
            // .... TODO
        }
        return "some string"
    }
}
public void main (String[] args) {
    ARGH argh = new ARGH();
    // Setup some X, Y, Z objects and their values here
    String D = argh.toString();
    // Do something to D
}

所以字符串和列表实际上不是全局变量所以我认为这不会起作用:

ObjVisitor v = new ObjVisitor() {
    @Override
    public void visit(X x) {
      A = x.value();
    }
    // And so on.
}

我假设我必须以某种方式将字符串A,B,C传递给访问方法,但我不知道如何做到这一点并仍然使用访问者模式。

2 个答案:

答案 0 :(得分:3)

在坚果壳中你会这样做:

  1. 为每种类型创建一个访问者界面ObjVisitor,其中包含一个visit - 方法。
  2. 将摘要accept(ObjVisitor v)添加到OBJ
  3. 为每个accept(ObjVisitor v) { v.visit(this); }实施添加OBJ
  4. 在循环中调用o.accept(yourVisitorImpl)
  5. 确实确实从Bringer128获得了一些代码。我详细阐述了一下并添加了String - 东西。

    import java.util.*;
    
    interface OBJ {
        String accept(ObjVisitor v);
    }
    
    interface ObjVisitor {
        String visit(X x);
        String visit(Y y);
        String visit(Z z);
    }
    
    class X implements OBJ {
        public String accept(ObjVisitor v){ return v.visit(this); }
    }
    class Y implements OBJ {
        public String accept(ObjVisitor v) { return v.visit(this); }
    }
    class Z implements OBJ {
        public String accept(ObjVisitor v) { return v.visit(this); }
    }
    

    用法:

    class Test {
        public static void main(String[] args) {
    
            List<OBJ> objs = Arrays.asList(new Z(), new X());
    
            ObjVisitor toStringVisitor = new ObjVisitor() {
                public String visit(X x) { return "X object"; }
                public String visit(Y y) { return "Y object"; }
                public String visit(Z z) { return "Z object"; }
            };
    
            String result = "";
            for (OBJ o : objs)
                result += o.accept(toStringVisitor) + "\n";
    
            System.out.println(result);
    
            // Prints
            // Z object
            // X object
        }
    }
    

    另一种(也许更好的方法)是让访问者实现维护一个StringBuilder,让visit-methods返回void,然后在循环之后调用stringVisitor.getCurrentString()或类似的东西。

答案 1 :(得分:0)

aioobe为你拼出了它,但这是实现的样子。

interface OBJ {
  void blah();
  // New method!
  void accept(ObjVisitor v);
}

class X implements OBJ {
  public void blah() {}
  @Override
  public void accept(ObjVisitor v) {
    v.visit(this);
  }
}

interface ObjVisitor {
  public void visit(X x);
  public void visit(Y y);
}

现在使用它:

public List<OBJ> a = new ArrayList<OBJ>();
public String A;
public String B;
public String C;

public void myMethod() {

  ObjVisitor v = new ObjVisitor() {
    @Override
    public void visit(X x) {
      A = x.value();
    }
    // And so on.
  }
  for (OBJ o : a) {
    o.accept(v);
  }
}