目前,我正在使用Java开发一个面向对象的心理数学程序。由于我对面向对象的设计原则比较陌生,所以很高兴知道代码与OOP主体的一致性如何,以及需要做哪些改进,包括:
MathQuestionGenerator (例如AdditionQuestionGenerator、SubtractionQuestionGenerator等)。-1项目概述:下面的代码本质上是一个GUI可以用来处理心理数学会话的模型。代码将生成20个随机问题,并跟踪时间和错误问题的数量。它可以处理5种类型的会话(加法、减法、乘法、除法或混合)和3种难度设置(容易、中等、困难)。
MathSession.java --表示用户回答20个问题的心理数学课。图形用户界面将调用startSession()并继续到submitAnswer(),直到所有20个问题都完成为止。然后,图形用户界面可以通过getFinalScore()获得用户的计算分数。
public class MathSession {
public SessionType type;
public SessionDifficulty difficulty;
public MathQuestionGenerator generator;
public MathQuestion currentQuestion;
public int progress;
public int numberWrongQuestions;
public final int numberOfQuestions = 20;
private long startTime;
private long endTime;
// Returns whether or not the session has completed
public boolean isComplete() {
return progress == numberOfQuestions;
}
// Calculates and returns a final score
// Returns -1 when the session has not been completed yet
public int getFinalScore() {
if (!isComplete()) {
return -1;
} else {
double secondsElapsed = (endTime - startTime)/ 1000;
double penalty = numberWrongQuestions * 5;
int score = (int) Math.round(secondsElapsed + penalty);
return score;
}
}
public MathSession(SessionType operator, SessionDifficulty difficulty) {
this.type = operator;
this.difficulty = difficulty;
this.generator = new MathQuestionGenerator(operator, difficulty);
}
// Starts the session
public void startSession() {
startTime = System.currentTimeMillis();
progress = 0;
numberWrongQuestions = 0;
currentQuestion = generator.generateQuestion();
}
// The user submits an answer, it is either right (returns true) or wrong (returns false)
public boolean submitAnswer(int answer) {
if (answer == currentQuestion.correct) {
progress++;
if (isComplete()) {
endTime = System.currentTimeMillis();
} else {
currentQuestion = generator.generateQuestion();
}
return true;
} else {
numberWrongQuestions++;
return false;
}
}
}MathQuestionGenerator.java --生成具有难度和会话类型的心理数学问题。
public class MathQuestionGenerator {
public SessionType type;
public SessionDifficulty difficulty;
private Random random;
public MathQuestionGenerator(SessionType type, SessionDifficulty difficulty) {
this.type = type;
this.difficulty = difficulty;
random = new Random();
}
// Generates a random math question given the session type and difficulty
public MathQuestion generateQuestion() {
int num1Max, num2Max, num1, num2, min = 1;
MathOperator operation = null;
if (type == SessionType.Addition) {
operation = MathOperator.Addition;
} else if (type == SessionType.Subtraction) {
operation = MathOperator.Subtraction;
} else if (type == SessionType.Multiplication) {
operation = MathOperator.Multiplication;
} else if (type == SessionType.Division) {
operation = MathOperator.Division;
} else if (type == SessionType.Mixed) {
// Choose an operation randomly
operation = random.nextInt(1) == 0 ?
(random.nextInt(1) == 0 ? MathOperator.Addition : MathOperator.Subtraction) :
(random.nextInt(1) == 0 ? MathOperator.Multiplication : MathOperator.Division);
}
if (operation == MathOperator.Addition || operation == MathOperator.Subtraction) {
if (difficulty == SessionDifficulty.Easy) {
num1Max = 12;
num2Max = 12;
} else if (difficulty == SessionDifficulty.Medium) {
num1Max = 100;
num2Max = 100;
} else {
num1Max = 10000;
num2Max = 10000;
}
} else {
if (difficulty == SessionDifficulty.Easy) {
num1Max = 12;
num2Max = 12;
} else if (difficulty == SessionDifficulty.Medium) {
num1Max = 100;
num2Max = 10;
} else {
num1Max = 100;
num2Max = 100;
}
}
num1 = min + random.nextInt(num1Max - min);
num2 = min + random.nextInt(num2Max - min);
MathQuestion question;
if (type == SessionType.Addition) {
question = new MathQuestion(MathOperator.Addition, num1, num2, num1 + num2);
} else if (type == SessionType.Subtraction) {
question = new MathQuestion(MathOperator.Subtraction, num1 + num2, num1, num2);
} else if (type == SessionType.Multiplication) {
question = new MathQuestion(MathOperator.Multiplication, num1, num2, num1 * num2);
} else {
question = new MathQuestion(MathOperator.Division, num1 * num2, num2, num1);
}
return question;
}
}MathQuestion.java -用两个数字表示一个数学问题,一个运算和一个正确的答案。
public class MathQuestion {
public MathOperator operator;
public int number1;
public int number2;
public int correct;
public MathQuestion(MathOperator operator, int number1, int number2, int correct) {
this.operator = operator;
this.number1 = number1;
this.number2 = number2;
this.correct = correct;
}
}public enum MathOperator {
Addition,
Subtraction,
Multiplication,
Division
}public enum SessionType {
Addition,
Subtraction,
Multiplication,
Division,
Mixed
}public enum SessionDifficulty {
Easy,
Medium,
Hard
}发布于 2019-12-21 18:39:21
欢迎来到代码评论,并感谢您分享您的代码!
我就是这么想的:
文件中元素的
)
在java文件中有一个元素顺序的约定。您违反的最重要的是,构造函数位于任何(非静态)方法之前。
注释应该解释为什么代码是这样的。您的评论只是重复代码本身所表达的内容,因此是无用的。
中工作
在构造函数MathSession()中,使用operator和difficulty两个参数创建MathQuestionGenerator实例。对于更多的这两个参数(分别是属性,它们被设置为),在类中不使用。
更好的方法是在MathQuestionGenerator之外创建MathSession()实例,并将MathQuestionGenerator实例作为构造函数参数传递给MathSession(),而不是operator和difficulty。
类MathQuestion是一个数据传输对象。在对象的LifeTime期间,它的大多数属性不会改变。因此,它们应该是final。
声明类public中的所有属性使它们可以从外部访问。这违反了OOP最重要的原则:信息隐藏/封装。因此,默认情况下声明属性private,并且只有在您有很好的理由这样做的情况下才更改它。
OOP并不意味着将代码“拆分”成具有随机继承关系的随机类。
OOP的最终目标是减少代码重复、提高可读性和支持重用以及扩展代码。
执行OOP意味着您遵循某些原则(除其他外):
代替分支
您创建了一些enum类型,这首先是一件好事。但是,您只使用枚举值来选择MathQuestionGenerator类中的执行分支。例如:
MathOperator operation = null;
if (type == SessionType.Addition) {
operation = MathOperator.Addition;
} else if (type == SessionType.Subtraction) {
operation = MathOperator.Subtraction;
} else if (type == SessionType.Multiplication) {
operation = MathOperator.Multiplication;
} else if (type == SessionType.Division) {
operation = MathOperator.Division;
} else if (type == SessionType.Mixed) {
// Choose an operation randomly
operation = random.nextInt(1) == 0 ?
(random.nextInt(1) == 0 ? MathOperator.Addition : MathOperator.Subtraction) :
(random.nextInt(1) == 0 ? MathOperator.Multiplication : MathOperator.Division);
}更好的方法是将各个分支中的“特殊行为”转换为枚举的各种常量:
public enum SessionType {
Addition{
return MathOperator.Addition;
},
Subtraction{
return MathOperator.Subtraction;
},
Multiplication{
return MathOperator.Multiplication;
},
Division{
return MathOperator.Division;
},
Mixed{
return random.nextInt(1) == 0 ?
(random.nextInt(1) == 0 ? MathOperator.Addition : MathOperator.Subtraction) :
(random.nextInt(1) == 0 ? MathOperator.Multiplication : MathOperator.Division);
};
public abstract MathOperator selectOperator();
}您的原始代码将更改为:
MathOperator operation = type.selectOperator();您的方法getFinalScore()返回一个特殊的值来告诉调用者出了什么问题(用户还没有回答足够多的查询)。更好的方法是抛出一个异常。
例外的使用是一个地雷领域。经验法则是,您确实使用异常来发出异常行为的信号,而不是实现控制流。在我看来,你的例子是一个角落的例子,因为还没有回答所有的问题显然不是“快乐的一天之路”。
异常的另一种选择可能是返回一个Java8 8-可选的,而不是原始的int。
https://codereview.stackexchange.com/questions/234434
复制相似问题