如何为编辑器正确使用具有不同形状的访问者模式
How to correctly use the visitor pattern with different Shapes for an Editor
我正在为不同的形状对象创建一个编辑器。我偶然发现了我认为真正符合我需求的访问者模式。
我有一个 Element
class 包含一个名为 attrs
的字段
public class Element {
...
private Shape attrs;
...
}
我的 Shape
class 使用访问者设计模式看起来像这样。
public abstract class Shape {
public abstract void accept(ShapeVisitor v);
public interface ShapeVisitor{
public void visit(CircleObject circle);
public void visit(RectangleObject rectangle);
}
}
Shape
的实际实例在 RectangleObject
class 中定义,它扩展了 Shape 并包含 Rectangle
字段。这种结构的原因是我正在使用 Jackson 序列化和反序列化特定 JSON 布局。
public class RectangleObject extends Shape {
private Rectangle rect;
public class Rectangle {
private String fill;
public String getFill() {
return fill;
}
public void setFill(String fill) {
this.fill = fill;
}
@Override
public void accept(JointShapeVisitor v) {
v.visit(this);
}
}
最后,我的编辑器实现了访问者方法。
public class Editor implements ShapeVisitor{
@Override
public void visit(CircleObject circle) {
}
@Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
visit(element.getAttrs()); // *** this does obv. not work ***
}
}
element.getAttrs()
returns JointShape
但是我这里需要一个CircleObject
或者一个RectangleObject
.
如何将正确的 ShapeObject 实例传递给访问方法?我做错了什么吗?
此致。
嗯...一个小错误。因为您在 Shape
class 中正确地声明了一个 accept
方法,您只需调用它:
element.getAttrs().accept(this);
因此只需将编辑器本身作为访问者来调用形状的接受方法。形状实现中的回调将调用正确的访问者方法。
你会做的是
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
element.getAttrs().accept(this);
}
并且您将获得对其中一种访问方法的回调。您没有得到的是 return 值。
处理起来可能有点棘手,因为回调代码突然与调用 accept
方法的方法无关。但是您经常希望在访问方法和调用 accept
的方法之间来回传递参数。为此,您可以在模式中添加一点:
@Override
public Object accept(JointShapeVisitor v, Object context) {
return v.visit(this, context);
}
}
public interface ShapeVisitor{
public Object visit(CircleObject circle, Object context);
..
}
也许使用一些泛型来使其类型安全。但即使没有你也可以突然做
public class Editor implements ShapeVisitor{
@Override
public Foo visit(CircleObject circle, Object context) {
return new Foo(circle, (String) context));
}
@Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
Foo foo = (Foo)element.getAttrs().visit(this, "Hello");
}
}
我正在为不同的形状对象创建一个编辑器。我偶然发现了我认为真正符合我需求的访问者模式。
我有一个 Element
class 包含一个名为 attrs
public class Element {
...
private Shape attrs;
...
}
我的 Shape
class 使用访问者设计模式看起来像这样。
public abstract class Shape {
public abstract void accept(ShapeVisitor v);
public interface ShapeVisitor{
public void visit(CircleObject circle);
public void visit(RectangleObject rectangle);
}
}
Shape
的实际实例在 RectangleObject
class 中定义,它扩展了 Shape 并包含 Rectangle
字段。这种结构的原因是我正在使用 Jackson 序列化和反序列化特定 JSON 布局。
public class RectangleObject extends Shape {
private Rectangle rect;
public class Rectangle {
private String fill;
public String getFill() {
return fill;
}
public void setFill(String fill) {
this.fill = fill;
}
@Override
public void accept(JointShapeVisitor v) {
v.visit(this);
}
}
最后,我的编辑器实现了访问者方法。
public class Editor implements ShapeVisitor{
@Override
public void visit(CircleObject circle) {
}
@Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
visit(element.getAttrs()); // *** this does obv. not work ***
}
}
element.getAttrs()
returns JointShape
但是我这里需要一个CircleObject
或者一个RectangleObject
.
如何将正确的 ShapeObject 实例传递给访问方法?我做错了什么吗?
此致。
嗯...一个小错误。因为您在 Shape
class 中正确地声明了一个 accept
方法,您只需调用它:
element.getAttrs().accept(this);
因此只需将编辑器本身作为访问者来调用形状的接受方法。形状实现中的回调将调用正确的访问者方法。
你会做的是
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
element.getAttrs().accept(this);
}
并且您将获得对其中一种访问方法的回调。您没有得到的是 return 值。
处理起来可能有点棘手,因为回调代码突然与调用 accept
方法的方法无关。但是您经常希望在访问方法和调用 accept
的方法之间来回传递参数。为此,您可以在模式中添加一点:
@Override
public Object accept(JointShapeVisitor v, Object context) {
return v.visit(this, context);
}
}
public interface ShapeVisitor{
public Object visit(CircleObject circle, Object context);
..
}
也许使用一些泛型来使其类型安全。但即使没有你也可以突然做
public class Editor implements ShapeVisitor{
@Override
public Foo visit(CircleObject circle, Object context) {
return new Foo(circle, (String) context));
}
@Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
Foo foo = (Foo)element.getAttrs().visit(this, "Hello");
}
}