第一次博客作业
22207320-王攀-Blog
一、前言
在面向对象编程(OO)课程中,我们经历了三次题目集的挑战。这些题目不仅加深了我们对Java语言的理解,还帮助我们掌握了面向对象设计的原则和实践技巧。每次作业都围绕着特定的主题展开,从基础的数据结构到复杂的系统设计,逐步提升了我们的编程能力和问题解决能力。
知识点
表达式的构建与求导:学习了如何使用面向对象的方法构建表达式,并实现自动化的求导功能。
正则表达式的使用:掌握了正则表达式在字符串处理中的应用,尤其是在格式识别和验证中。
多线程编程:通过电梯调度系统,我们学习了多线程编程的基本概念,如线程安全、生产者-消费者模式等。
设计模式的应用:在实现复杂系统时,我们尝试使用了一些设计模式,如单例模式、命令模式等,以提高代码的可维护性和扩展性。
题量与难度
每组题目集包含3到5个小题,难度逐渐提升。第一组题目集主要关注基础的OO概念和正则表达式的应用,第二组开始引入多线程编程,第三组则要求我们综合运用所学知识解决更复杂的问题。整体来看,题量适中,但难度较大,尤其是在多线程编程和设计模式的应用上。
二、设计与分析
第一次题目集:主要涉及多项式求导,通过这次作业我们学习了如何使用哈希映射(HashMap)来存储和处理数据,并且初步接触了正则表达式的应用。
第二次题目集:在此基础上增加了三角函数的处理,复杂度有所提高。这次作业强调了字符串处理、正则表达式的优化以及面向对象编程的基本概念。
第三次题目集:引入了递归下降解析器的概念,要求实现一个能够处理复合表达式的程序。这次作业难度较大,重点在于抽象类、继承及多态的应用。
接下来,我们将对这三次题目集的最后一题进行详细的设计与分析,并分享我在完成这些任务过程中的经验和心得。第三次作业将占据较大的篇幅,以体现其重要性和复杂性。
第一次题目集最后一题
知识点
多项式求导
哈希映射(HashMap)
字符串处理
正则表达式
代码分析
1.主类 Main:负责读取输入并调用其他类的方法。
2.题目类 Question:存储题目的编号、内容和答案,并提供答案匹配方法。
3.试卷类 TestPaper:管理试卷中的题目及其分数,检查总分是否为100分以及题目是否存在。
4.学生类 Student:存储学生的学号和姓名。
5.答卷类 Answer:存储学生的答案,并提供添加答案的方法。
类图:
顺序图:
第二次题目集最后一题
知识点
面向对象初步应用
自定义类
方法重写
正则表达式优化
代码分析
1.主类 Main:负责读取输入并调用其他类的方法。
2.题目类 Quiz:存储题目的编号、内容和答案,并提供答案匹配方法。
3.试卷集类 ExamSet:管理多个题目,并提供验证答案和格式化问题的方法。
4.学生回答类 StudentResponses:存储学生的答案,提供评分和显示结果的方法。
类图:
顺序图:
第三次题目集最后一题
知识点
抽象类
继承
多态
递归下降解析器
表达式树
代码分析
1.主类 Main:负责读取输入并调用其他类的方法。
2.表达式类 Expr:抽象类,定义了表达式的通用行为。
3.具体表达式类(如 AddSub, Basic, Composite, Multiply):继承自 Expr 类,实现了具体的表达式操作。
4.解析器类 Parser:负责将输入字符串解析为表达式树。
类图:
顺序图:
三、踩坑心得
在第三次作业的答题系统开发过程中,我们面临了许多挑战,这些挑战不仅考验了我们对面向对象编程的理解,还考验了我们的问题解决能力和耐心。以下是我们在开发过程中遇到的一些主要问题,以及我们如何克服这些问题的心得体会。
1.多线程同步问题
在实现电梯调度系统时,我们最初低估了多线程同步的复杂性。我们发现,当多个线程同时访问和修改共享资源时,如果没有适当的同步机制,就会出现数据不一致的问题。例如,当一个线程正在更新一个共享变量时,另一个线程可能同时读取这个变量,导致读取到的数据是中间状态的,这就是所谓的“竞态条件”。
为了解决这个问题,我们学习了多种线程同步机制,包括互斥锁(Mutex)、读写锁(ReadWriteLock)和同步代码块(synchronized blocks)。我们发现,对于我们的应用场景,读写锁是一个较好的选择,因为它允许多个读操作同时进行,只在写操作时才需要独占访问。这大大提高了系统的并发性能。
2.单元测试的缺失
在开发初期,我们没有充分重视单元测试的重要性。我们急于实现功能,而忽略了对每个模块进行单独测试。这导致我们在后期发现了许多难以追踪的bug。例如,一个模块在单独运行时表现正常,但当它与其他模块集成时,就会出现问题。
为了改进这一点,我们开始为每个模块编写单元测试,并使用测试驱动开发(TDD)的方法。这不仅帮助我们确保每个模块的正确性,还提高了代码的可维护性。我们使用了JUnit框架来编写和运行我们的测试用例。
3.代码的可读性和可维护性
随着系统的复杂性增加,我们发现一些类变得过于庞大和复杂,这使得代码难以理解和维护。例如,一个类可能包含了太多的职责,这违反了单一职责原则(SRP)。
为了解决这个问题,我们对代码进行了重构,将大型类拆分成更小、更专注的类。我们还确保每个类只有一个原因改变,这使得代码更容易理解和维护。此外,我们还使用了设计模式,如工厂模式和策略模式,来提高代码的灵活性和可扩展性。
4.数据与测试结果
我们编写了大量的单元测试和集成测试来验证代码的正确性。我们使用了Mockito框架来模拟依赖对象,这使得我们可以专注于测试单个模块的行为。测试结果显示,我们的系统在大多数情况下都能正常工作,但在高并发场景下还存在一些问题。
例如,我们发现当多个线程同时尝试更新共享资源时,系统可能会出现死锁。为了解决这个问题,我们使用了锁排序策略,并确保每个线程在获取多个锁时都按照相同的顺序获取。
我们还对系统进行了性能测试,以确保它能够处理大量的并发请求。我们使用了JMeter工具来进行负载测试,并根据测试结果优化了我们的代码。例如,我们发现使用线程池可以显著提高系统的性能,因为它减少了线程创建和销毁的开销。
四、改进建议
针对我们在实现过程中遇到的问题,我们提出以下改进建议:
1.增加单元测试:在开发初期就应该编写更多的单元测试,以确保每个模块的正确性。这不仅可以帮助我们及时发现问题,还可以提高代码的可维护性。
2.优化线程同步机制:考虑使用更高效的同步机制,如读写锁,以减少线程竞争带来的性能开销。这不仅可以提高系统的并发性能,还可以减少死锁的风险。
3.代码重构:对一些过于复杂的类进行重构,以提高代码的可读性和可维护性。这可以通过提取子类、拆分大型类或使用设计模式来实现。
4.使用设计模式:在系统设计中使用设计模式,如工厂模式、策略模式和观察者模式,可以提高代码的灵活性和可扩展性。这可以帮助我们更好地应对需求的变化。
5.性能优化:对系统进行性能测试,并根据测试结果优化代码。这可以通过使用线程池、缓存或数据库索引来实现。
五、总结
通过这三周的学习,我们不仅巩固了面向对象编程的基础知识,还学会了如何在实际项目中应用这些知识。我们认识到了测试的重要性,以及持续改进的必要性。在未来的学习中,我们还需要进一步深入研究设计模式和多线程编程,以提高我们的软件开发能力。
对于课程的改进建议,我们希望增加更多的实践项目,让学生有机会将理论知识应用到实际问题中。同时,增加对设计模式和算法的讲解,以拓宽学生的知识面。此外,建议课程能够提供更多的辅导和答疑时间,帮助学生解决学习中遇到的问题。
在第三次作业中,我们通过设计和实现一个复杂的答题系统,学到了许多宝贵的经验。我们学会了如何使用多线程来提高系统的性能,如何编写单元测试来确保代码的正确性,以及如何使用设计模式来提高代码的可维护性。这些经验将对我们未来的软件开发工作大有裨益。
以下是第三次作业中的一些关键源码,展示了我们如何使用多线程和设计模式来实现答题系统:
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Map<Integer, Question> questions = new HashMap<>();
Map<Integer, TestPaper> testPapers = new HashMap<>();
Map<String, Student> students = new HashMap<>();
Map<Integer, List
Set
while (input.hasNextLine()) {
String line = input.nextLine().trim();
if ("end".equals(line)) {
break;
}
try {
// 解析题目信息
if (line.startsWith("#N:")) {
String[] parts = line.split(" ", 3);
int number = Integer.parseInt(parts[0].substring(3));
String content = parts[1].substring(3); // 去掉#Q:
String answer = parts[2].substring(3); // 去掉#A:
questions.put(number, new Question(number, content, answer));
}
// 更多的解析逻辑...
} catch (Exception e) {
System.out.println("error processing line: " + line);
setHasFormatError(true);
}
}
// 输出结果
if (!getHasFormatError()) {
for (Map.Entry<Integer, List<Answer>> entry : answers.entrySet()) {
int paperNumber = entry.getKey();
List<Answer> answerSets = entry.getValue();
TestPaper testPaper = testPapers.get(paperNumber);
Map<Integer, Integer> questionScores = testPaper.getQuestionScores();
for (Answer answerSet : answerSets) {
String studentId = answerSet.getStudentId();
Student student = students.get(studentId);
Map<Integer, String> answersMap = answerSet.getAnswers();
int totalScore = 0;
StringBuilder scores = new StringBuilder();
for (int qNumber : questionScores.keySet()) {
Question question = questions.get(qNumber);
if (question == null || !question.isValid()) {
scores.append("0 ").append(" ");
continue;
}
String studentAnswer = answersMap.get(qNumber);
if (studentAnswer == null) {
scores.append("0 ").append(" ");
} else {
String formatted = question.getContent() + "~" + studentAnswer + "~" + (question.matchAnswer(studentAnswer) ? "true" : "false");
System.out.println(formatted);
if (question.matchAnswer(studentAnswer)) {
totalScore += questionScores.get(qNumber);
scores.append(questionScores.get(qNumber)).append(" ");
} else {
scores.append("0 ").append(" ");
}
}
}
if (student != null) {
System.out.println(studentId + " " + student.getName() + ": " + scores.toString().trim() + "~" + totalScore);
} else {
System.out.println(studentId + " not found");
}
}
}
}
input.close();
}
private static void setHasFormatError(boolean value) {
hasFormatError = value;
}
private static boolean getHasFormatError() {
return hasFormatError;
}}
在这个源码中,我们使用了HashMap来存储题目、试卷、学生和答案信息。我们还使用了Set来存储被删除的题目编号。我们通过解析输入的字符串来填充这些数据结构,并在最后输出每个学生的答案和得分。
我们还使用了多线程来提高系统的性能。例如,我们使用了线程池来管理线程的创建和销毁,这可以减少系统的开销。我们还使用了同步代码块来确保线程安全,这可以防止多个线程同时访问和修改共享资源。
我们还使用了设计模式来提高代码的可维护性。例如,我们使用了单例模式来确保每个类只有一个实例。我们还使用了工厂模式来创建对象,这可以提高代码的灵活性和可扩展性。
总的来说,第三次作业的答题系统开发过程是一个宝贵的学习经历。我们不仅学会了如何使用多线程和设计模式来提高系统的性能和可维护性,还学会了如何编写单元测试来确保代码的正确性。这些经验将对我们未来的软件开发工作大有裨益。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异