当您使用访问者模式并且需要在访问者方法中获取变量时,如何继续?
我看到两种方法。第一个使用匿名类:
// need a wrapper to get the result (which is just a String)
final StringBuild result = new StringBuilder();
final String concat = "Hello ";
myObject.accept(new MyVisitor() {
@Override
public void visit(ClassA o)
{
// this concatenation is expected here because I've simplified the example
// normally, the concat var is a complex object (like hashtable)
// used to create the result variable
// (I know that concatenation using StringBuilder is ugly, but this is an example !)
result.append(concat + "A");
}
@Override
public void visit(ClassB o)
{
result.append(concat + "B");
}
});
System.out.println(result.toString());
优点和缺点:
- 优点:您不需要为这个小行为创建类文件
- 缺点:我不喜欢这种情况下的“final”关键字:匿名类的可读性较差,因为它调用外部变量,并且您需要使用包装器来获取请求的值(因为使用关键字final,您无法重新分配变量)
另一种方法是创建一个外部访问者类:
public class MyVisitor
{
private String result;
private String concat;
public MyVisitor(String concat)
{
this.concat = concat;
}
@Override
public void visit(ClassA o)
{
result = concat + "A";
}
@Override
public void visit(ClassB o)
{
result = concat + "B";
}
public String getResult()
{
return result;
}
}
MyVisitor visitor = new MyVisitor("Hello ");
myObject.accept(visitor);
System.out.println(visitor.getResult());
优点和缺点:
- 优点:所有变量都在干净的范围内定义,您不需要包装器来封装请求的变量
- 缺点:需要外部文件,必须在accept方法之后调用getResult()方法,这非常难看,因为您需要知道函数调用顺序才能正确使用访问者
您,在这种情况下您的做法是什么?首选方法?另一个想法?
最佳答案
嗯,这两种方法都是有效的,而且在我看来,这实际上取决于您是否愿意重用代码。顺便说一句,您的最后一个“缺点”点并不完全有效,因为您不需要“外部文件”来声明类。它很可能是一个内部类......
也就是说,我使用访客的方式是这样的:
public interface IVisitor<T extends Object> {
public T visit(ClassA element) throws VisitorException;
public T visit(ClassB element) throws VisitorException;
}
public interface IVisitable {
public <T extends Object> T accept(final IVisitor<T> visitor) throws VisitorException;
}
public class MyVisitor implements IVisitor<String> {
private String concat;
public MyVisitor(String concat) {
this.concat = concat;
}
public String visit(ClassA classA) throws VisitorException {
return this.concat + "A";
}
public String visit(ClassB classB) throws VisitorException {
return this.concat + "B";
}
}
public class ClassA implements IVisitable {
public <T> T accept(final IVisitor<T> visitor) throws VisitorException {
return visitor.visit(this);
}
}
public class ClassB implements IVisitable {
public <T> T accept(final IVisitor<T> visitor) throws VisitorException {
return visitor.visit(this);
}
}
// no return value needed?
public class MyOtherVisitor implements IVisitor<Void> {
public Void visit(ClassA classA) throws VisitorException {
return null;
}
public Void visit(ClassB classB) throws VisitorException {
return null;
}
}
这样,被访问的对象不知道访问者想要用它们做什么,但它们确实返回访问者想要返回的任何内容。您的访问者甚至可以通过抛出异常来“失败”。
我几年前写了这个的第一个版本,到目前为止,它在任何情况下都对我有用。
免责声明:我只是将其拼凑在一起,质量(甚至编译)无法保证。但你明白了...:)
关于java - 使用访问者模式时是匿名还是真实的类定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7244511/