1

我有一个设计问题:

  • 问题类:有一个问题和答案(字符串)
  • TextQuestion 类:普通文本问答
  • NumberQuestion 类:问题(字符串)、答案(数字 - 整数、浮点数...),并使用 epsilon 值检查答案

但我对 NumberQuestion 有疑问。我必须选择正确的答案,将其转换为数字,并与用户的答案进行比较。那么我怎样才能得到答案呢?使用 getter 方法并不安全。还是我的设计不好?我该如何改变?

public abstract class Question {
  private String question;
  private String answer;

  public Question(String question, String answer) {
      this.question = question;
      this.answer = answer;
  }

  public boolean checkAnswer(String yourAnswer) {
      // default implementation
  }
}

class TextQuestion extends Question {
  // Answer and Question is always string type, it's OK, not problem
}

class NumberQuestion extends Question {
  // Question is String, OK
  // Answer: input is number, accept approximately
  // Ex: Question: 1/3 = ?
  //     Answer: 0.3 or 0.33 or 0.333 are accepted (using an Epsilon value)

  // so must override checkAnswer
  public boolean checkAnswer(String yourAnswer) {
      // HOW can I do?
  }
}
4

3 回答 3

4

我不明白为什么需要对子类(或任何客户端代码,就此而言)隐藏答案。客户端代码肯定首先需要知道答案才能创建一个TextQuestionNumberQuestion实例。

您应该从类中抽象出测试的逻辑以及答案类型Question

public abstract class Question<AnswerType> {
  private String question;
  private AnswerType answer;

  public Question(String question, AnswerType answer) {
    this.question = question;
    this.answer = answer;
  }

  public abstract boolean checkAnswer(AnswerType yourAnswer);

  protected AnswerType getAnswer() {
    return answer;
  }
}

class TextQuestion extends Question<String> {
  public TextQuestion(String question, String answer) {
    super(question, answer);
  }

  public boolean checkAnswer(String yourAnswer) {
    return answer.equals(yourAnswer);
  }
}

class NumberQuestion extends Question<Double> {
  private double epsilon;

  public NumberQuestion(String question, Double answer, double epsilon) {
    super(question, answer);
    this.epsilon = epsilon;
  }

  public boolean checkAnswer(Double yourAnswer) {
    return Math.abs(getAnswer() - yourAnswer) < epsilon;
  }
}
于 2012-07-01T05:31:43.523 回答
1

如果您的答案可以有不同的类型,您也可以在抽象类中使用泛型。

public abstract class Question<T> {
    private final String question;
    protected final T answer;

    public Question(String question, T answer) {
        this.question = question;
        this.answer = answer;
    }

    //Default implementation
    public boolean checkAnswer(T yourAnswer) {
        return answer.equals(yourAnswer);
    }
}

当你定义子类时:

class NumberQuestion extends Question<BigDecimal> {
    ...
    private final BigDecimal epsilon;

    public NumericQuestion(String question, BigDecimal answer, BigDecimal epsilon) {
        super(question, answer);

        this.epsilon = epsilon;
    }

    @Override
    public boolean checkAnswer(BigDecimal yourAnswer) {
        BigDecimal result = this.answer.subtract(yourAnswer).abs();

        return (result.compareTo(epsilon) == -1); // check whether result < epsilon
    }
}

顺便说一句,使用 BigDecimal 进行浮点计算比使用 double 更好。有很多关于这个的好文章。如果对您感兴趣,您可以“谷歌”这个问题。

如果您需要为浮点数设置比例,您可以使用大小数轻松完成此操作,例如:

result = result.setScale(5);

并且要小心,因为 BigDecimal 类是不可变的(不完全,但这是另一个问题),并且当您尝试更改它的状态时会返回新实例。

于 2012-07-01T05:20:37.833 回答
0

我不确定您是否熟悉泛型类,但这在这种情况下是合适的。你可以谷歌它。:-)

如果您不想这样做,您可以随时将两者转换yourAnswerthis.answer相同的类型,然后您可以找到绝对差异并确保它们低于特定阈值。

于 2012-07-01T05:11:59.240 回答