最终架构设计
由于一开始并未特别思考代码扩张,修改,迭代等问题,导致整体的代码相对比较堆叠混乱 (屎山) ,该架构值得修改调整的地方有很多.
架构设计
类表
类 | 功能 |
---|---|
Adventurer | 冒险者,需要有冒险者的属性和动作 |
Bottle | 药水瓶,需要有其属性 |
Commodity | 价值体接口,需要有价值体共有的方法,价值体需实现该接口 |
Equipment | 装备,需要有其属性 |
Food | 食物,需要有其属性 |
RegularBottle | 常规药水瓶,继承Bottle |
RecoverBottle | 恢复药水,继承Bottle,新增ratio |
ReinforcedBottle | 增强药水,继承Bottle,新增ratio |
RegularEquipment | 常规装备,继承equipment |
CritEquipment | 暴击装备,继承Equipment,新增critical |
EpicEquipment | 史诗装备,继承Equipment,新增ratio |
Shop | 商店类,用来处理买卖事件 |
Task | 任务类,用来解析和处理任务 |
Main | 主类,负责输入和调用task |
类关系图
架构调整与反思
开发过程中的架构调整
新增Task类
在迭代过程中,我总是在写完一定量代码之后才想到更好的架构,所以在迭代开发中,我做的大的架构调整较少,主要做的调整是新增Task类.考虑到Main类只是程序的主入口,不应再Main类写太多的代码,尤其是在main方法里写太多代码,于是考虑将输入\输入的解析与任务\任务的解析分开来,于是抽离出了Task类.
开发完成后的架构反思
Commodity的优化
在原先架构中,仅在Commodity接口中,写了个抽象方法getType(),这会导致在每个实现Commodity接口的类均需实现getType()方法,这不妥,尤其是如果还要迭代开发时会造成一定的麻烦.优化可以考虑写一个默认方法,用instanceof关键字来分类讨论
default String getType() {
...
}
几个工具类的增加
AdventurerManager类
根据上述架构,会出现这样一个问题:Adventurer的代码十分的复杂堆叠,可维护性和可复用性不高,这是因为将Adventurer的属性和行为,以及一些查找\计算\管理等功能性的方法写在了同一个类里面.因此一个好的做法,是将功能性的一些方法封装成一个工具类AdventurerManager.
Log类
上述架构还会出现的一个问题是将战斗日志的处理融入到了Adventurer和Task类里面,这样也会导致混乱,代码可维护性不高.因此将战斗日志的一些处理方法封装成Log工具类
Junit的心得体会
使用Junit可以帮助我们比较方便的找出比较明显的错误,但是通过这几次对Junit的使用,我发现对于一些比较隐蔽的问题,第一需要比较强的测试,要能覆盖到问题所在;第二需要自己对代码逻辑(或题目逻辑)的正确理解;这二者也是Junit的局限性,对于规模量巨大的代码,构造Junit测试是一个相当大的工程,对于测试者对于代码逻辑的理解的考验也是巨大的.总之,Junit是一个比较大的学问,我还需要继续进行探索和学习
面向对象学习心得体会
从面向过程到面向对象的转变,对我来说并不困难.随着编写Java代码量的增加,我越来越发现面向对象是一个非常自然的编程思想.我需要一个新的东西,我就将这个东西封装成一个类,然后在这个类中编写这个东西的属性(成员变量)和行为(方法)就可以了.如果发现几个类有很多共性,还可以利用继承的编程思想,来提高代码的复用性.在我看来面向对象的一个十分强大之处就是多态,利用多态,我们可以将代码的灵活性和复用性提高到很高的一个层次.
当然在OOPre课程中,感受最大的还是代码的架构问题.笔者一开始并不重视代码架构,看到题目提笔就写,导致后期迭代过程代码已经堆成屎山,对我的迭代开发造成巨大的麻烦,后悔没有一开始做好代码架构,这给我的教训就是一定要在写代码前做好架构分析和准备,拒绝屎山,从我做起!
对OOPre课程的简单建议
- 对于一些题目的描述,还是要更清楚些,不要引起歧义
- 每次作业可以对架构相关的问题给予一些提示,能让初学者重视架构问题,并少走一些弯路