一、前言:
本次的大作业,包含了两个部分,一个是之前的1-3大作业(答题程序)还剩余的一次迭代,另外两个是最近做的电路设计的迭代,总而来说,这些大作业都是对于自己能力的考验,也是对自己的提升。
二、设计与分析:
大作业4最后一题:
1.源码分析:
这次的迭代相比于上次的内容,主要是增加了如下
- 题目:增加了题目类型,包括多选题,填空题了
- 对于类的设计,主要是需要使用继承的思想,这些多选题,填空题都是可以继承于题目类,然后重写其中的方法。
- 对于判分,就需要增加多选题的判分逻辑,填空题的判分逻辑。因为会有半对的情况产生,所以需要考虑。
其实我这里也是使用小巧思
class MCQuestion extends Question { // 定义选择题类,继承题目类public MCQuestion(int number, String content, String standardAnswer) {super(number, content, standardAnswer);}
}class FQuestion extends Question { // 定义填空题类,继承题目类public FQuestion(int number, String content, String standardAnswer) {super(number, content, standardAnswer);}
}
其实不难发现,我这个完全就是一个虚假的继承,因为我其实还是把他当那种单选题做了,不过能出一个半对的情况。只是我分开存储了答案,然后就会有我如下的判定:
boolean isAllCorrect = standardAns.equals(providedAns); // 对于一模一样的答案直接通过,针对填空题
boolean isCorrect = containsAllCharacters(MstandardAns, MproviedAns); // 对于错序的选择题,如标准答案是:ABD,给出答案是:DBA
boolean ishalfCorrect = containspartCharacters(MstandardAns, MproviedAns); // 判断是否有包含,针对半对的情况,不能有多余字符
可以看见我的是有三种情况的,然后分开判定,这样就能处理多选题和半对的情况。也算是一个投机取巧的办法?
2.SourceMontor分析结果:
3.UML图:
4.时序图
大作业5最后一题:
1.源码分析
这是第一次新的题,就是对于电路电器的模拟
我做出了如下设计:
- 电气设备类(Electrical_equipment)
- 属性:
- identifier: 设备的唯一标识符(例如,VCC、GND等)。
- inputVoltage: 输入电压(默认值为0V)。
- outputVoltage: 输出电压(默认值为0V)。
- number: 设备编号。
input 和 output: 分别表示设备的输入和输出端口。
- 方法:
- getOutputVoltage(): 返回输出电压,调用 computeOutput() 进行计算。
- setInputVoltage(double inputVoltage): 设置输入电压。
- computeOutput(): 抽象方法,用于每个设备根据输入电压计算输出电压,具体实现由子类提供。
- 具体设备类
- 电压源(Voltage_source): 输出固定电压220V,表示电源设备。
- 接地(Ground): 输出固定电压0V,表示接地设备。
- 控制设备(如 Switch, Binning_governor, Continuous_governor): 用于调节电路的开关状态、调速或调节电压输出。
- 受控设备(如 Light, Fan): 由电压控制,执行具体的控制操作,如灯的亮度或风扇的转速。
每个设备类继承自 Electrical_equipment 并实现了 computeOutput() 方法,计算设备的输出电压或亮度等。
-
控制设备类
Switch: 用于控制电路开关状态。电路的状态(开或关)会影响设备的电压输出。toggle() 方法改变开关状态。
Binning_governor: 分档调速器,通过切换档位控制电压输出的比例。共有4档,档位0至3。
Continuous_governor: 连续调速器,输出电压比例在0至1之间,可以细粒度调整输出电压。
这些设备通过输入调节命令(例如 #K1, #F2+ 等)来控制设备的状态。 -
电路连接和设备控制
ProcessSystem 类负责解析输入命令并管理设备。输入包括设备连接(例如 [VCC 1])和设备控制命令(如 #K2, #F3+ 等)。
解析设备连接:parseConnection() 方法通过正则表达式解析输入的设备连接命令。根据设备连接,更新设备列表 deviceList。
设备控制:parseControlEquipment() 方法解析并执行控制命令,比如切换开关状态或调整调速器档位。
串联电路(SeriesCircuit): 设备通过 SeriesCircuit 类连接,模拟串联电路的行为。电压从 VCC(电压源)流向其他设备,并根据设备的状态计算每个设备的输出电压。
在串联电路中,电流流过每个设备时,可能会遇到开关(Switch),若开关关闭,则电路中断,电压为0V。
输出计算:computeSystemOutput() 方法会计算整个系统的输出,并将结果按设备编号排序输出。
其实是以巨大的继承关系,
如图:
可以见到总的父类是Electrical_equipment,然后是Voltage_source、Ground、Switch、Binning_governor、Continuous_governor、Light、Fan等具体设备类,最后是ProcessSystem类负责管理设备。
2.SourceMontor分析结果:
3.UML图
4.时序图
大作业6最后一题:
1.源码分析
此次迭代基于上次的基础上添加了并联电路,以及新的受控设备,对于新的受控设备来说,改的不多,只是增加了一个新的类来继承Fan,然后重写了computeOutput()方法,计算风扇的转速。并且在处理设备的时候增加对于落地扇的操作即可。
最主要的是新增的并联,思路也比较简单,我是计算电阻分压来做的,在并联的类里,有
private List< SeriesCircuit > seriesCircuits; 来存放串联电路,通过computeOutput()计算分压,然后再计算总电压。
另外,我把之前的设备里的comouteOutput()方法改成了compute(),因为现在同一以compute()来计算设备的各种参数值。comouteOutput()就主要用于处理电压,以及电阻等了。
2.SourceMontor分析结果:
3.UML图
4.时序图
三、踩坑心得
- 在大作业4的实现中,尝试通过继承关系来简化多种题型的设计(如选择题、填空题等)。虽然这种设计看起来符合面向对象的设计原则,但实际上并没有充分利用继承的优势,而是出现了“虚假的继承”——多选题和填空题本质上和单选题差别不大,继承只是为了区分不同的题型。然而,这种设计使得代码的可扩展性变差,因为后续若需要对新类型的题目进行扩展(如判断对错规则),则不得不修改现有类。但是那一次我也只会这样考虑了
- 在大作业5和大作业6的电路模拟中,涉及到了设备之间的数据流和控制逻辑。尤其是在串联和并联电路的实现过程中,需要仔细设计每个设备的输入输出接口以及控制命令的解析。最初在设计控制命令的解析时,难以保证命令的顺序和格式的一致性,导致程序出错或行为不符合预期。
- 电路模拟中的每个设备都有不同的计算逻辑,如电压源、电压控制器、负载设备等,而每个设备的输出都可能受到其他设备的影响。调试时发现电路在某些情况下输出不正常,往往是因为某个设备的状态或参数没有正确传递。比如在串联电路中,若一个开关状态未被正确更新,可能导致电路中断,输出为零。在并联电路中,之前没有分开compute()和computeOutput(),导致在计算分压的时候,没有考虑到电阻的值,导致计算错误。
- 大作业6中,我实现了并联电路的模拟。并联电路的输出电压需要通过电阻分压来计算,虽然思路清晰,但实际编码时,如何准确模拟电流分流和电压分配,尤其是在不同设备和电路组合时,给我带来了一些困惑。起初,我没能很好地处理串联电路和并联电路之间的相互影响,导致某些情况下计算结果不准确。
四、改进建议
- 尽量避免为了继承而继承,特别是在子类和父类之间差异不大的情况下。可以考虑通过接口或者策略模式来提高代码的灵活性和可维护性。
- 对于大作业4的答题程序来说,应该是进一步优化进程的,可以增加属性:答案的集合等信息,以便于判分。这样相对于我的程序更加优良
- 对于大作业6来说,我的成绩是94分的样子,在今天走的时候想到,似乎有个地方没有改掉,就是在sort中,没有把A(落地扇)加上去,导致其实落地扇是没有加入排序的。
总结
通过这次的大作业,我不仅巩固了面向对象的设计思维,也深入理解了如何将抽象的电路模型转化为具体的代码实现。从设计继承关系到电路的模拟,每一部分都考验了我的编程能力和解决问题的思路。通过这次迭代,我收获了很多实践经验,也发现了自己的不足之处,特别是在如何设计灵活、可扩展的系统方面。