How to make a GUI for a polymorphic class

design-patternspolymorphism

Let's say I've got a test builder, so that teachers can create a bunch of questions for a test.

However, not all questions are the same: You have multiple choice, text box, matching, and so on. Each of these question types need to store different types of data, and need a different GUI for both the creator and for the test-taker.

I'd like to avoid two things:

  1. Type checks or type casting
  2. Anything related to the GUI in my data code.

In my initial attempt, I end up with the following classes:

class Test{
    List<Question> questions;
}
interface Question { }
class MultipleChoice implements Question {}
class TextBox implements Question {}

However, when I go to display the test, I'd inevitably end up with code like:

for (Question question: questions){
    if (question instanceof MultipleChoice){
        display.add(new MultipleChoiceViewer());
    } 
    //etc
}

This feels like a really common problem. Is there some design pattern that allows me to have polymorphic questions while avoiding the items listed above? Or is polymorphism the wrong idea in the first place?

Best Answer

You can use a visitor pattern:

interface QuestionVisitor {
    void multipleChoice(MultipleChoice);
    void textBox(TextBox);
    ...
}

interface Question {
    void visit(QuestionVisitor);
}

class MultipleChoice implements Question {

    void visit(QuestionVisitor visitor) {
        visitor.multipleChoice(this);
    }
}

Another option is a discriminated union. This will depend very much on your language. This is much better if your language supports it, but many popular languages don't.

Related Topic