BUAA-OOpre总结
即面向对象先导课程,绝世好课!!!
所有的代码均可以前往我的github中获取
Part1-作业背景
一个非常经典的冒险类游戏
你是一个穿越到魔法大陆上的冒险者,在旅途中,你需要收集各种道具(药水瓶和事物),使用各种装备,招募其他冒险者加入队伍,提升自己的等级并体验各种战斗,你可以雇佣冒险者,雇佣者会在适当的时候向你提供帮助。同时加入了商店功能,在这里可以进行各种商品的购买与出售。
Part2-架构设计
最终的架构设计
从Main
类出发。
- 对于IO,首先对于输入使用
MyScanner
进行处理,将结果得到一个ArrayList
里面,再对这个进行解析,然后调用Manager类进行具体操作。
主要操作在Manager
类中,主要的方法也在Manager
类中:happy::happy::happy:
-
对于要求,我主要是三个大的类进行处理,
Adventurer,Backpack,FightMode
这几个来进行处理。 -
对于每个
Adventurer
的管理再Manager
里面用一个HashMap
来实现。对于每个adventurer
,在这里面管理调度Bottle,Food,Equipment
等,同时对于放进背包的则将其放到Backpack
里面进行管理调度。 -
进入战斗模式则有一个专门
FightMode
管理进入的adventurer
和进行的操作,对于每个adventurer
状态的改变都是在Adventurer
类里面实现的,实现高内聚。同时后续的增加接口和继承也是直接在Bottle
的基础上继承,每次调用都只需要在相应的方法里面实现。
总体还是非常优雅的,尽可能的实现了高内聚和低耦合,每次修改代码时感觉上是非常方便的,或许能够间接体现比较好的一个架构建造。
(我也是几乎到最后才知道有package
这个东西,虽然加上后文件结构会更加好看,但对于代码架构本身帮助不大)
架构设计中的调整
主要是学到什么或者看到其他同学有什么好的就思考一下是否比我的好,并进行相关学习后进行调整
- IO处理
其中一大调整在于输入处理,随着输入变得更加复杂,需要加入正则表达式进行操作处理后(主要是其中某一个功能有不定行输入),我便将输入处理专门用了一个Scanner
类进行处理,以下为具体实现细节:
public class MyScanner {
private static Scanner scanner = new Scanner(System.in);
public static int getOperationLine() {
return Integer.parseInt(scanner.nextLine().trim()); // 读取行数
}
private static int n = getOperationLine();
public static ArrayList<ArrayList<String>> getInputInfo() {
ArrayList<ArrayList<String>> inputInfo = new ArrayList<>(); // 解析后的输入将会存进该容器中, 类似于c语言的二维数组
for (int i = 0; i < n; ++i) {
String nextLine = scanner.nextLine(); // 读取本行指令
String[] strings = nextLine.trim().split(" +"); // 按空格对行进行分割
ArrayList<String> operation = new ArrayList(Arrays.asList(strings));
if (operation.get(0).equals("14")) {
int k = Integer.parseInt(operation.get(2));
for (int j = 0; j < k; j++) {
String nextLine1 = scanner.nextLine();
operation.add(nextLine1.trim());
}
}
// System.out.println(operation);
inputInfo.add(operation); // 将指令分割后的各个部分存进容器中
}
// System.out.println(inputInfo);
return inputInfo;
}
public static int getN() {
return n;
}
}
- 结构调整
在老师讲解完不要再Main里面进行 太多具体的操作后,我便将之前大量的属性和方法移动到了Mynager
类中,在这个类中进行不同指令的操作处理,以及正则表达式匹配等。具体实现细节如下:
public class Manager {
private static HashMap<Integer, Adventurer> adventurersMap = new HashMap<>();
private static FightMode fightMode = new FightMode();
private static boolean printTestFlag = false;
private static ArrayList<String> strings;
private static final Shop shop = Shop.getShopInstance();
public static void operation(int n, ArrayList<ArrayList<String>> inputInfo) {
for (int i = 0; i < n; ++i) {
strings = inputInfo.get(i); // 获取第i行指令
switch (strings.get(0)) { // 获取第i行指令的第一个部分
case "1":
// Adventurer.add();
adventurerAdd(strings);
break;
...
}
}
}
- 接口与继承
后面在要求实现对Bottle
类和Equipment
类进行继承,以及对几个价值体实现接口时都有对结构进行相应的调整,大体上也是正常不过的基于教程的修改感觉大家的应该都大差不差
以下为UML类图
各个类的属性
各个类的方法概览
Part2-使用Junit的心得体会
上一次用到这种模块性检测的还是在matlab里面
这种模块化的测试确实会方便于去寻找具体是哪一方面有问题,但是我自己本人对于这种工程量很大之后如何处理这些测试指令感到犯难,不太懂得具体如何使用。
同时我觉得很好的一点是主动去想办法提高测试的覆盖率,会帮助我狠狠地提高代码的鲁棒性,增加很多对于特殊情况的考虑。
Part3-学习OOpre的心得体会
很早之前就已经听6系学长讲过OO这一种编程方法,当时对于所谓的高内聚低耦合方面还不太懂,当时学长讲的大多数是基于C语言如何进行类似的开发的
当自己真正开始学习之后,面向对象确实是很好的一种编程理念,特别是中间利用到继承这些时更加感受到了一种代码上的很爽的感觉。
当然,Java真的是一种非常接近自然语言的函数语言,用起来很爽!
Part4-对OOpre课程的建议
- 感觉可以讲一些java本身的一些高级的语法,我也是后来才了解到一些,感觉用起来真的很爽
- 我刚开始写Junit和后来写Junit都有点使用取巧的办法,自己也是为了满足测试率去编写的,中间几次甚至是讲几百行的中测数据直接作为输入处理后的二维数组进行处理,或许可以想办法提高Junit的实用性
OOpre绝世好课!!真的在这个过程中学到了很多东西,也非常感谢助教、老师、同学给我提供的帮助。
谢谢nrjj!syf大佬!!还有董佬教了我好多新鲜的东西……谢谢各位!