一、作业最终的架构设计, 在迭代中的架构调整及考虑
1.最终架构设计:

共20个类,1个接口use,其中 Equipment 和 Bottle 是 abstract类。
PS:继承关系用的黑色箭头,应用接口用的白色箭头,调用用的单线箭头。
2.迭代中架构调整及考虑:
(1)架构调整一:增加 CommandHandler 和 InputProcesser
// 调整前:Main类一不小心就会超过行数限定,过不了CheckStyle
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
HashMap<String,Adventurer> adventurers = new HashMap<>();
int n = Integer.parseInt(scanner.nextLine());
for (int i = 0; i < n; i++) {
String line = scanner.nextLine();
String[] parts = line.split("\\s+");
// 大量if-else处理各种命令...
}
}
}
// 调整后:各司其职,Main只需要使用以下两个类,简洁许多
public class InputProcessor {
public void processInput() {
// 只负责输入读取
}
}
public class CommandHandler {
public void handleCommand(String[] parts) {
// 只负责根据指令调用函数
}
}
调整后,每个类只负责一个特定功能,Main 类不用担心超过规定行数。
(2)架构调整二:创建Use接口
public interface Use {
void use(Adventurer target);
}
//Bottle和Spell都实现这个接口
public abstract class Bottle extends Item implements Use
public abstract class Spell implements Use
// 调整前
if (item instanceof HpBottle) {
target.changeHitPoint(effect);
} else if (item instanceof AtkBottle) {
target.changeAtk(effect);
} // ...更多else if
// 调整后
usableItem.use(target);
- 原因:Bottle和Spell都有use方法,但代码重复,使用时的类型判断复杂,需要大量instanceof检查。
- 好处:所有"可使用"的物品有统一接口,新增可使用物品只需实现Use接口,无需修改使用代码。
(3)架构调整三:增加Lexer和Parser
lr命令的输入格式复杂:A(B,C(D,E)) ,需要解析嵌套结构。
增加两个类,将解析问题分为词法+语法两个阶段:
-
Lexer:词法分析,将输入字符串分解为token。
-
Parser:语法分析,根据语法规则构建对象关系。
总结:
-
发现重复,提取共性抽象:Use接口
-
内容过多 ,分解模块:CommandHandler、InputProcessor
-
复杂度增加 ,特别的解决方案:Lexer、Parser
二、使用JUnit的心得体会
1.找到隐藏 bug:
在JUnit 中设计边界情况和异常情况的测试用例,提前发现了代码中未处理的问题,帮助自己debug。
2.增加重构自信:
在架构调整过程中,如果修改代码较多,难免担心会改变原来已经实现的功能。使用JUnit,可以快速验证原来的功能是否没有改变。
例如在上下级关系的存储设计中,我一开始是每个冒险者管理所有下级,这样会导致存储空间不足;修改成每个冒险者只管理直接下级后,运行JUnit发现原来的方法都全部通过测试,让我确定我在修改过程中没有引入新的bug。
3.培养良好的方法设计习惯:
为了让方法便于测试,我会不自觉地减少方法间的依赖,避免编写过长的复杂方法。这让我在编码时下意识去保证方法的单一性和独立性,养成了好习惯。
三、学习OOPre的心得体会
1.从面向过程到面向对象的思维转变
面向过程编程中,我们通过函数的顺序调用实现功能。比如完成一个 “战斗” 指令,可能会先写 “计算攻击力”“扣减生命值”“判断胜负” 等一系列函数,再按顺序执行。
但在面向对象编程中,我们关注的是“谁来做” 和 “做什么”。先识别场景中的对象,再定义对象的属性和行为,最后通过对象间的相互调用实现功能。
这种转变让我意识到,面向对象思维能让代码结构更清晰,尤其是在复杂场景中,对象的独立和封装降低了代码的耦合度,让逻辑更加清晰。
2.抽象化思维的深化
抽象化是从具体事物中提炼共性,忽略细节,用更通用的概念描述问题,从而提升代码的复用性和扩展性。
例如,Item是对 Bottle和Equipment的抽象,它们都有 id、type、效果值,因此被抽象为抽象类 Item,统一定义这些共性属性和方法,而具体的 Bottle 和 Equipment 只需关注自身的特有行为,如 Bottle 的 use 方法。
再如Use接口抽象了“使用”这一行为,无论是 Bottle 还是 Spell,只要实现 use 方法,就可以被 Adventurer 的 useItem 统一调用,无需关心具体是药水还是法术。
四、对OOPre课程的简单建议
- 讲解核心知识点时,多搭配简短代码示例,因为新学一门语言刚开始确实是无从下手,只能先模仿,然后再融会贯通。
- 讲设计模式时,可以增加一个“无模式实现”与“用模式实现”的优劣对比,因为我看完教程其实没有很明显感受到加上设计模式的优势,加上对比或许能让我更好理解设计模式的作用。
354





