BUAA_OOP_2024_碎碎念总结
架构设计
学习心得体会
类与对象
翻出去年的代码,看到下面的杰作,不禁感叹诗人握持啊!
1 2 3 4 5 6
| adventure.addBottle(adventure.getBottles(), botId, botName, capacity); public void addBottle(HashMap<Integer, Bottle> bottles, int botId, String botName, int capacity) { }
|
当时并未理解面向对象中“类”这一概念,按照C语言的想法把所有需要的信息作为函数参数传入类的方法中,忽视属性在类内部的可见性o(~ヘ~o#)
对象管理与容器使用
经过OO正课U3的TLE折磨,回看当初的代码略显稚嫩,没有做到容器的高效管理o(~ヘ~o#)
一个典型的用Botname
作为键映射的HashMap
,也让我用HashSet
这么水灵灵的遍历上了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| private HashSet<Bottle> bagBottles;
public void carryBot(HashMap<Integer, Bottle> bottles, HashSet<Bottle> bagBottles, String id) { ..... Bottle bot1 = bottles.get(botId); if (!bagBottles.contains(bot1)) { for (Bottle obj : bagBottles) { if (obj.getName().equals(bot1.getName())) { num++; } } if (num < max) { bagBottles.add(bot1); } } }
|
今年直接火速爆改,HashMap
套HashMap
轻松拿下(。•̀ᴗ-)✧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| private HashMap<String, HashMap<Integer, Bottle>> bagBottles;
public void carryBot(int botId) { int max = getCE() / 5 + 1; Bottle bot1 = bottles.get(botId); if (bagBottles.containsKey(bot1.getName())) { HashMap<Integer, Bottle> botMap = bagBottles.get(bot1.getName()); if (botMap.size() < max) { botMap.put(botId, bot1); } } else { HashMap<Integer, Bottle> botMap = new HashMap<>(); botMap.put(botId, bot1); bagBottles.put(bot1.getName(), botMap); } }
|
今年oop没有针对ArrayList
和HashSet
卡TLE,正课不会这么心慈手软了,xd接招(。•̀ᴗ-)✧
继承和接口
作为两种不同的代码复用机制,父类是通过提炼多个类的重复部分形成的,而接口服务于多个类之间共性的行为。好好读指导书的我当然在去年就明确了概念,做的超棒(。•̀ᴗ-)✧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| class Bottle implements Commodity { public Bottle(int id, String name, int capacity, long price) { this.id = id; this.name = name; this.capacity = capacity; this.isFilled = true; this.price = price; } public void usedBy(Adventure adventurer) { adventurer.setHitPoint(adventurer.getHitPoint() + capacity); } } public class RecoverBottle extends Bottle { private double ratio;
public RecoverBottle(int id, String name, int capacity, long price, double ratio) { super(id, name, capacity, price); this.ratio = ratio; }
@Override public void usedBy(Adventure adventurer) { adventurer.setHitPoint(adventurer.getHitPoint() + (int) Math.floor(adventurer.getHitPoint() * ratio)); }
}
interface Commodity { public void printInfo();
public int getId();
public long getPrice(); } public class Bottle implements Commodity { @Override x3 ...... }
interface Guard { boolean fight(Adventure adv); String getType(); } public class Shd implements Guard { @Override x2 ...... }
|
大三最近在上的编译课中,也体现了继承思想的使用,不禁感叹学会OO受益终生,背景是这样的:
从前小汀种了一棵树,叫做抽象语法树AST,这颗树的不同节点Node,有着不同的类型NodeType。现在我们考虑根节点的类型为CompUnit,它有一些孩子节点,类型分别为 Decl、FuncDef等。
小汀利用继承的思想顺利完成了如下的作业!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class Node { protected ArrayList<Node> children; protected NodeType nodeType;
public Node(NodeType type, ArrayList<Node> children) { this.children = children; this.nodeType = type; } }
public enum NodeType { CompUnit, Decl, FuncDef }
public class CompUnit extends Node { public CompUnit(NodeType type, ArrayList<Node> children) { super(type, children); } } public class Decl extends Node { public Decl(NodeType type, ArrayList<Node> children) { super(type, children); } } public class FuncDef extends Node { public FuncDef(NodeType type, ArrayList<Node> children) { super(type, children); } }
|
设计模式
观察者模式与去年考察类似,不同的是,今年oop重磅推出了工厂设计模式的练习,体现出课程组向真正生产场景逐步靠拢的决心和魄力(。•̀ᴗ-)✧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class TreasureFactory { public static Treasure createTreasure(Guard guard) { switch (guard.getType()) { case "Shd": return new ShdTreasure(); case "Flm": return new FlmTreasure(); case "Stn": return new StnTreasure(); case "Wnd": return new WndTreasure(); case "Frz": return new FrzTreasure();
default: throw new IllegalArgumentException("Unknown guard type"); } }
public static void factory(Adventure adv) { Guard shd = new Shd(); if (shd.fight(adv)) { Treasure treasure = TreasureFactory.createTreasure(shd); treasure.showInfo(); treasure.useBy(adv); } else { return; } .... } }
|
这又让我想起了编译课中,也体现了工厂模式的使用,不禁再次感叹学会OO受益终生,书接上文:
小汀想只传入节点类型NodeType和节点名称name就能得到不同子类的具体对象。
小汀利用工厂模式的设计思想顺利完成了如下的作业!
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class NodeFactory { public static Node newNode(NodeType type, ArrayList<Node> children) { switch (type) { case CompUnit -> { return new CompUnit(type, children); } case Decl -> { return new Decl(type, children); } .... } }
|
输入解析
去年没有实现层次化架构,输入解析和业务处理一起耦合在我的Main
里┐=͟͟͞͞( ̄ー ̄)┌
今年架构先行,起手就是一个Manager
类,来进行不同指令对应业务的分发
1 2 3 4 5 6 7 8 9
| public void handle(String[] strings) { if (strings[0].equals("1")) { addAdv(strings); } else if (strings[0].equals("2")) { addBot(strings); } else if (strings[0].equals("3")) { addEqu(strings); } }
|
拜读助教czx的标程之后,顿觉其设计之优雅简洁,雅!!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Solver { private final HashMap<Integer, SolveFunction> solvers = new HashMap<>(); private final HashMap<Integer, Adventurer> adventurers = new HashMap<>();
public Solver() { solvers.put(1, this::solve1); solvers.put(2, this::solve2); }
public void solve(ArrayList<String> input) { int id = Integer.parseInt(input.get(0)); SolveFunction func = solvers.get(id); if (func != null) { func.solve(input); } else { System.err.println("Error! No solver for " + id); } } }
|
Debug的心得体会
今年即使偷看标程偷看数据点,验题的时候还是特别狼狈啊!!!

我的bug包括但不限于
- 删除
Equipment
时没有没有判断HashMap
背包中的装备是否id相同(因为HashMap
使用装备名作为索引)
- 援助被雇佣者的次数要重新从零计算
- 所有冒险者失去的体力值的总和输出了负值
- 携带和拥有总是搞混
- ……..
我debug的方法包括但不限于
偷看标程偷看数据点
- 使用printf,追溯每一位冒险者的活动轨迹,
我想给它完整的一生
- 使用debug,re的时候巨好用
- 幻想有人能开发测评机,这个到正课真的很重要(つ﹏⊂)
后话
两次挑战oopre,变的是我的知识储备、代码能力、debug水平,我发现
- 没有人是生来会写代码,oop练习迭代的意义就是在实践中提升代码能力,现在我可以很自豪的说,窝辉鞋黛玛啊!
- 没有人是生来懂得debug的,只要耐心阅读测试数据,反复推敲指导书,没有测评机的帮助我也找到了自己的问题!
- 没有人是生来懂得架构的,在不断设计与不断重构中,锤炼自己的设计思想,方能自然写出适应自己业务需求的代码!
岁月更迭,纵使架构不断迭代,性能不断优化,我们从未改变的是
- 不忘来时路,oop课程的初心是,大家一起努力提升优化,今后能从容应对实际生产研发中遇到的困难
- 不忘来时路,oop课程的目标是,收获知识方法,吸取经验教训,更好与oo正课衔接
下一次正课再见,我们来日方长!!!( ´͈ ᵕ `͈ )◞♡