下的 TreeVisitor 完成了这些:
清单 7. 用一个访问者来跟踪 TreePrinter 的缩进
import java.io.OutputStream;
import java.io.PrintStream;
class TreePrinter implements TreeVisitor {
private int amountOfIndentation;
// The stream to which we are printing.
PrintStream out;
public TreePrinter() {
this.amountOfIndentation = 0;
this.out = System.out;
}
public TreePrinter(OutputStream _out) {
this();
this.out = new PrintStream(_out);
}
TreePrinter(int _amountOfIndentation) {
this();
this.amountOfIndentation = _amountOfIndentation;
}
TreePrinter(int _amountOfIndentation, OutputStream _out) {
this();
this.amountOfIndentation = _amountOfIndentation;
this.out = new PrintStream(_out);
}
/**
* Prints an amount of whitespace proportional to the
* current degree of indentation.
*/
public void indent() {
for (int i = 0; i < this.amountOfIndentation; i++) {
this.out.print(" ");
}
}
public Object forLeaf(Leaf that) {
// Since leaves are empty, they are not printed.
// Returns a dummy object to satisfy TreeVisitor interface.
return new Object();
}
public Object forBranch(Branch that) {
TreePrinter innerPrinter =
new TreePrinter(this.amountOfIndentation + 1, this.out);
this.indent();
this.out.println(that.getValue());
that.getLeft().accept(innerPrinter);
that.getRight().accept(innerPrinter);
// Returns a dummy object to satisfy TreeVisitor interface.
return new Object();
}
}
诊断Java代码: 设计可扩展的应用程序,第2部分(4)
时间:2011-02-11 IBM Eric E. Allen
但另一方面,当我们扩展这个 TreeVisitor 以包含单元素叶这种情况时,先的方法将构造错误的 TreeVisitor 类型实例:
清单 8. 单元素叶导致 TreePrinter 构造类型错误的实例
class TreePrinter2 extends TreePrinter implements TreeVisitor2 {
public TreePrinter2(int _amountOfIndentation) {
super(_amountOfIndentation);
}
public Object forNonEmptyLeaf(NonEmptyLeaf that) {
this.indent();
this.out.println(that.getValue());
// Returns a dummy object to satisfy TreeVisitor interface.
return new Object();
}
}
...
// But the inherited method forBranch will construct an
// instance of TreePrinter, not TreePrinter2!
public Object forBranch(Branch that) {
TreePrinter innerPrinter =
new TreePrinter(this.amountOfIndentation + 1, this.out);
this.indent();
this.out.println(that.getValue());
that.left.accept(innerPrinter);
that.right.accept(innerPrinter);
// Returns a dummy object to satisfy TreeVisitor interface.
return new Object();
}
如果 TreeCopier2 的一个实例试图访问一个 Tree ,而这个 Tree 带有是 NonEmptyLeaf 的双亲的一个 Branch ,则在 NonEmptyLeaf 的 accept 方法中强制类型转换成 TreeVisitor2 将失败。
一种答案:向工厂(factory)方法求助
这个问题的一个解决方案,最初是由 Krishnamurthi 等人提出的(请参阅 参考资料),该解决方案是用工厂方法而不是构造器来构造 |