Question

I have several objects that all extend a Shape basic class. For every object I want to display a different object editor, as eg a Line has different properties to edit than a 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
}

For every implementation of Shape there is only one single Editor implementation. What pattern can I use here to: show the right editor for a shape according to the shapes implementation type (instanceof)?

I do not want the Shapes (domain model) themself to know which the right editor is.

StrategyPattern cannot be used here as in onEditEvent() it would have to be known which implementation the shape is of, and pass strategy accordingly.

VisitorPattern cannot be used here as I would have the Shapes implement some kind of interface Visitable which would force them to implement a edit(IEditorVisitor) method, and by this pollute the domain model with information about how it will be displayed in UI.

What else can I do here?

Update:

Example of how I'd to the Visitor Pattern (though I don't like it as I have to "pollute" the domain model with things like edit(editor) methods. I'd like to avoid this.

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
    }
}
Was it helpful?

Solution

VisitorPattern cannot be used here as I would have the Shapes implement some kind of interface Visitable which would force them to implement a edit(IEditorVisitor) method, and by this pollute the domain model with information about how it will be displayed in UI.

Well, no it doesn't have to give the domain model information about how it is displayed or edited. It need only give the domain model knowledge that it is visited.

Just don't name your visitor interface IEditorVisitor and don't name the IVisitable method edit.

Visitor is very much suited to this sort of problem.

I would do it more like:

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
    }
}

Note that this is essentially equivalent to your implementation sketch, only changing names, so that the function of editing is only in the editor.

The function names accept and visit are commonly used in descriptions of this pattern, and reflect the pattern. They can of course be changed, but I don't see the need, and it's certainly better to keep them from being explicitly tied to the editing function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top