271
社区成员
发帖
与我相关
我的任务
分享
程序分为核心实体层、业务逻辑层、数据层、输入解析层和异常处理层。
包含 Main 和 CommandHelper
程序将输入拆分为行后使用逐行传入 CommandHelper 对指令进行处理,CommandHelper 维护所有活动的 Adventurer 并包含所有具体业务逻辑的实现。在 Main 中对捕获的异常进行解析并打印。
AdventurerhitPoint, baseAtk, baseDef, mana, money)以及各类物品(bottleList, equipmentList, spellList)。fight,use,takeItem,changeHitPoint help 等。BagpackcarriedWeapon)、一件护甲 (carriedArmour),以及最多 10 瓶药剂 (carriedBottles)。getWeaponAttack, getArmourDefense)。该层定义了游戏中的所有可交互物品,采用经典的继承结构。
| 类名 | 继承/实现 | 核心属性 | 核心功能 |
|---|---|---|---|
Item (abstract) | Object | id | 所有物品的基类。 |
Equipment (abstract) | Item | ce (Combat Effectiveness) | 装备基类,拥有战斗效果值。 |
Armour | Equipment | (extends) | 护甲类型装备。 |
Weapon (abstract) | Equipment | WeaponType (Sword, Magicbook) | 武器类型装备。 |
Bottle | Item | effect, BottleType | 药剂类,具有即时效果(Hp, Atk, Def, Mana)。使用后标记为 used。 |
Spell | Object | manaCost, power, SpellType (Heal, Attack) | 法术类,消耗 Mana,可用于治疗或攻击。注意:Spell 与 Item 独立,但逻辑相似。 |
FactorycreateBottle, createEquipment, createItem),根据输入的类型字符串 (e.g., "HpBottle", "Sword") 实例化对应的具体物品对象。CommandHelper 中的物品添加)解耦。包含 Lexer 与 Parser
使用梯度下降对 lr 命令进行解析,完成批量导入
定义了一系列自定义运行时异常 (RuntimeException),用于在业务逻辑中精确地指示错误类型,并允许 Main 方法进行统一处理。
CantBeTarget :FailureType: isDead, isBoss, notAlly。FailToUse :FailureType: AlreadyUsed, LackOfMana, AtkLow。NoSuchItem:NotUsable:use 命令)。在此之前,所有核心业务在 Main 函数中实现,方法行数容易超过限制,不便进行 JUnit 测试。
将核心业务从 Main 中提取出为 CommandHelper ,方便进行测试,并能调用非静态方法。
在此次作业中首先出现了异常指令,考虑到后续异常指令可能的增多以及维护的便捷程度,定义一些运行时异常管理这些错误。
增加异常处理层,维护异常指令的输出。
将Equipment 重写为抽象类,并在新类中维护具体方法
增加 Factory ,将物品实例化与 CommandHelper 解耦
后续架构未发生较大变动,仅对一些类添加方法
在使用 JUnit 中往往测试一个较大的类时会遇到需要重复实例化某种类,如
@Test
public void testConstructorAndGetId() {
Armour armour = new Armour("armour1", 30);
assertEquals("armour1", armour.getId());
}
@Test
public void testGetCe() {
Armour armour = new Armour("armour1", 30);
assertEquals(30, armour.getCe());
}
@Test
public void testGetType() {
Armour armour = new Armour("armour1", 30);
assertEquals("Armour", armour.getType());
}
这时我们可以使用 @Befor 来进行统一的初始化,如
@Befor
public void setup() {
Armour armour = new Armour("armour1", 30);
}
单元测试可以进行模块化的测试,在测试时自底向上对正确性进行保证,这样可以大大减少测试的困难
好的测试用例有以下几个特点:
已知输入和预期输出,即在测试执行前就已知。
已知输入需要测试的先决条件,预期输出需要测试后置条件。
单元测试对测试用例有以下几个要求:
以及一些 Idea 使用技巧,你可以右键->生成->测试来一键生成对应的测试,接下来只需要在函数中填写代码即可。

面向对象的特性
封装(Encapsulation):把数据和操作这些数据的代码放到同一个对象里,并通过访问控制(如 private/public)隐藏内部实现,只暴露必要接口,从而保护对象的状态不被任意修改。
例:class BankAccount { private balance; public deposit(), withdraw() }
继承(Inheritance):子类从父类复用属性和行为,可以扩展或改写(override)父类的功能,体现“is-a”关系,便于代码重用和层次组织。
例:class Dog extends Animal { void bark() {} }
多态(Polymorphism):不同类型的对象通过统一的接口被同一段代码处理,调用在运行时绑定到具体实现(尤其是方法重写),提高灵活性和可扩展性。
例:Animal a = new Dog(); a.speak(); // 调用 Dog 的实现
抽象(Abstraction):从具体事物中抽出共性,定义抽象类或接口来描述“做什么”,而把“怎么做”留给具体子类,实现关注点分离和实现隐藏。
例:interface Shape { double area(); } // Circle/Rectangle 去实现
在面向对象的开发中,代码的耦合性降低,便于对对象进行维护,修改不会影响外部调用,扩展性强,新增功能只需添加方法。
面向对象和面向过程的区别
面向对象是注重对象的,在解决问题的时候会把事务抽象成对象的概念,并让每个对象维护自己的属性,执行自己的方法。
增加课程强度,增加 hack互测, 增加课程作业次数,通常在一定量的作业后才会形成较为正式的代码架构,增加作业次数后可以使得代码调整的机会变多,并在形成正式架构后体会在面向对象编程中添加新业务的方便之处。
将最终心得体会拆分为每周博客作业,有助于博客内容的充实和社区交流。