我在理解树的访客设计模式时遇到了一些麻烦。根据我的理解,树本身需要一个接受方法,它将接收访问者界面的参数。当您遍历树时,visitor.visit()方法需要访问树中的每个节点和数据。
假设树需要是私有内部类。
我要挂起的部分是树的父类需要有一个方法,需要访问树的所有节点,并将访问者界面作为参数。
我还是Java新手,我非常感谢任何方向。
答案 0 :(得分:0)
虽然访问者模式似乎经常以不同运行时类型的节点树的方式呈现,但重要的是要理解访问者模式的基本特征是双重调度。因此,访问者模式同样适用于您希望根据对象的类自定义行为的任何情况,但不能确切地知道该类的确切内容。
示例:
interface Shape {
public void accept(ShapeVisitor v);
}
interface ShapeVisitor {
public void visit(Circle c);
public void visit(Square s);
public void visit(Shape h);
}
class Circle implements Shape {
double radius;
public void accept(ShapeVisitor v) {
v.visit(this); // The correct overload is chosen at compile time
}
}
class Square implements Shape {
double edge;
public void accept(ShapeVisitor v) {
v.visit(this); // The correct overload is chosen at compile time
}
}
class AreaVisitor implements ShapeVisitor {
double area;
public void visit(Circle c) {
area = Math.PI * c.radius * c.radius;
}
public void visit(Square s) {
area = s.edge * s.edge;
}
public void visit(Shape h) {
// A Shape implementation other than Square or Circle
throw new RuntimeException(
"I don't know how to compute the area of a " + h.getClass());
}
}
AreaVisitor
可以计算它理解的任何形状的面积,即使形状类本身没有提供任何方法,即使特定类型的形状不是静态知道的。 (看看马,没有树!)
当您碰巧有一棵树时,访客的各种visit()
方法可以选择访问哪些子节点,或访问过的节点可以在其中做出决定accept()
方法。哪个更合适取决于访问者界面的性质和访问的类型。在任何一种情况下,如果访问者打算以某种方式遍历树,那么通常通过询问根节点accept()
访问者对象来启动该过程。
如果碰巧有一个对象代表整个树(除了根节点),那么我刚才描述的设计选择也必须在那个级别上进行。您可以通过将访问者传递给容器对象的某个方法来启动访问。该方法当然可以将访问者传递给树的根节点的accept()
方法。但是,如果容器恰好是为访问者设计的类,那么它也可以选择将自己传递给访问者visit()
方法中的适当的一个。
请注意,访问者模式取决于访问者要区分的类型(示例中为Circle
,Square
和Shape
)在Visitor接口的范围及其所有具体实现中。您可以使用它来访问其他类型的对象,但它们必须是访问者所设计类型之一的子类型。