2

我有几个对象都扩展了一个Shape基本类。对于我想要显示不同对象的每个对象editor,例如 a 与 aLine具有不同的要编辑的属性Rectangle

class Shape;
class Line extends Shape;
class Rectangle extends Shape;

List<Shape> shapes;

void onEditEvent(Shape shape) {
    new ShapeEditorPopup(shape);
    //how to avoid instanceof checks here
}

对于每个实现,Shape只有一个Editor实现。我可以在这里使用什么模式:根据形状实现类型 ( instanceof) 为形状显示正确的编辑器?

我不希望Shapes(域模型)自己知道哪个编辑器是正确的。

StrategyPattern不能在这里使用,因为onEditEvent()它必须知道形状是哪个实现,并相应地传递策略。

VisitorPattern不能在这里使用,因为我将Shapes实现某种interface Visitable强制他们实现edit(IEditorVisitor)方法的实现,并由此污染域模型,其中包含有关如何在 UI 中显示的信息。

我还能在这里做什么?

更新:

我如何使用访问者模式的示例(尽管我不喜欢它,因为我必须用edit(editor)方法之类的东西“污染”域模型。我想避免这种情况。

interface Editable {
    public void edit(IEditor editor);
}

public interface IEditor {
    public void edit(Shape shape);
}


class Line extends Shape implements Editable {  
    @Override
    public void edit(IEditor editor) {
        editor.edit(this);
    }
}

class EditorImpl implements IEditor {
    void edit(Line line) {
        //show the line editor
    }
    void edit(Rectangle rect) {
        //shwo the rectangle editor
    }
}
4

1 回答 1

3

VisitorPattern 不能在这里使用,因为我会让 Shapes 实现某种接口 Visitable,这将迫使它们实现 edit(IEditorVisitor) 方法,并由此污染域模型,其中包含有关如何在 UI 中显示的信息。

好吧,不,它不必提供有关如何显示或编辑的域模型信息。它只需要给出它被访问的领域模型知识。

只是不要命名您的访问者界面IEditorVisitor,也不要命名IVisitable方法edit

访客非常适合这类问题。

我会这样做更像:

public interface IVisitableShape {
    void accept(IShapeVisitor v);
}

public interface IShapeVisitor {
    void visit(Line line);
    void visit(Rectangle rectangle);
}

public class Line extends Shape implements IVisitableShape {

    @Override
    public void accept(IShapeVisitor v) {
        v.visit(this);
    }
}

public class EditorImpl implements IShapeVisitor {
    public void visit(Line line) {
        //show the line editor
    }
    public void visit(Rectangle rect) {
        //show the rectangle editor
    }
}

请注意,这本质上相当于您的实现草图,只是更改名称,因此编辑功能仅在编辑器中。

函数名称acceptvisit常用的描述这种模式,并反映模式。它们当然可以更改,但我认为没有必要,而且最好不要将它们明确绑定到编辑功能。

于 2013-03-16T16:34:12.373 回答