面向对象程序设计第二阶段学习总结
1、前言
OOP三次题目集中聚焦于面向对象程序设计与实际应用相结合,相比与上次,本次的三次题目集更需要我们设计时充分考虑系统的可复用性、可维护性与可扩展性,进一步提升我们设计类和方法的能力。未避免部分同学能力不够,给予了后续迭代提示。
其中,第四次作业集主要知识点集中在:对父类与子类的设计,子类对父类的继承以及对多态的应用,此外,还需要利用Comparator接口对电路原件进行排序;题量相对而言有明显提升,我设计并实现了12个类,共耗时5天;难度中等,需先解决抽象父类电路元件,再完成子类与门、或门、非门、异或门、同或门每一个电路元件的输入和输出以及重写Comparator接口的compare方法用于排序,重点集中在多态的应用,难点为识别多层级联电路的输入信息并转化为电路信息完成输出;此外,由于可能需要进行元件的复用,一个元件的输出信号可能成为另一个电路元件的输入信息,需要避免这个元件还未输出任何信号就被其他元件使用。
第二次题目集在第一次作业集的基础上又考察了系统的可复用性、可维护性与可扩展性。题目量大大地增加了,增加了包含多输入输出的组合电路元件(如数据选择器)和元件引脚类型(除输入、输出之外,增加控制引脚,如三态门)与第一次相比又增加了四个实物类(三态门、译码器、数据选择器、数据分配器),抽象父类电路元件增加新属性控制引脚,共耗时7天;难度偏难,需要处理更复杂的输入流,识别更加复杂的输入信息并转化为电路信息完成输出;而且,由于译码器、数据选择器、数据分配器输出引脚与控制引脚不止一个,需要理解并分析它们的输出信息所对应的编码规律和每一个输入信息所对应的引脚;此外,译码器、数据选择器、数据分配器输出引脚与控制引脚不止一个同样导致了它们的输出信息可能有所不同,需改变输出方式。
第六次题目集在第四次作业集的基础上增加子电路,增加程序异常输入的检测。题目量变化并不算太大,对我而言需设计并实现13个类,主要是需要采用组合模式,将子电路和电路元件作为抽象的元件类的子类,即可以将子电路看作一种组合型的电路元件,再增加对输入内容的判断,当出现各类异常输入情况时,电路应输出相应提示。此次共耗时10天;难度较难,如果系统的可复用性、可维护性与可扩展性较差的话需要改写大量代码,耗时巨大。重点在于如何让系统区分子电路与主电路,识别多层级联电路的输入信息并转化为电路信息完成输出,避免将正常输入信息当成错误信息;难点在于找到各种错误输出之间的特点,使用合适的逻辑区分不同的错误信息。
2.设计与分析
设计:
第四次题目集,它的需求为按照与门、或门、非门、异或门、同或门的顺序依次输出所有元件的输出引脚电平,同类元件按编号从小到大的顺序排序,如果某个元件的引脚没有接有效输入,元件输出无法计算,程序输出结果忽略该元件。类图如下:
首先需要 Signal(信号类) 来存储每个信号的名称和电平值;一个 GetSignal(信号输入类) 负责读取输入数据并构建信号链表,供 SetComponent(电路组件装配类) 连接元件与信号,再由 CircuitComparator(排序类) 按类型和编号排序电路元件,并通过调用 Andgate、Orgate、NotOrgate、Xorgate、Xnorgate(各类门电路) 的 Output 方法 计算逻辑结果,计算完成后由 Main(主类) 判断并输出满载门电路的最终信号状态,实现整个电路的装载与执行过程。
第五次题目集,它的需求为按照与门、或门、非门、异或门、同或门、三态门、译码器、数据选择器、数据分配器的顺序依次输出所有元件的输出引脚电平,同类元件按编号从小到大的顺序排序,如果某个元件的引脚没有接有效输入、输入输出之间断开(如三态门)或控制引脚输入无效,元件输出无效,程序输出忽略该元件;译码器不输出引脚电平,输出其输出为0的引脚的编号(如“M(3)1:3”代表译码器M3的输出引脚Y3输出0,其他引脚输出1);数据分配器按引脚编号从小到大的顺序输出所有输出引脚的信号,无效状态引脚输出“-”(如“F(2)1:--0-”代表分配器F1的输出引脚W2输出0信号,其他三个引脚为无效状态)。类图如下:
首先需要 Signal(信号类) 来存储每个信号的名称和电平值;一个 GetSignal(信号输入类) 负责读取输入数据并构建信号链表,供 SetComponent(电路装配类) 解析电路连接关系并绑定信号,再由 CircuitComparator(排序类) 按类型和编号排序电路元件,并通过调用 Andgate、Orgate、NotOrgate、Xorgate、Xnorgate、TriStateBuffer、Decoder、DataSelector、DataDistributor(各类电路元件) 的 Output 方法 计算逻辑结果,计算完成后由 Main(主类) 判断并输出有效电路元件的最终信号状态,实现整个电路的装载与执行过程。
第六次题目集,它的需求为无错误时按照与门、或门、非门、异或门、同或门的顺序依次输出所有元件的输出引脚电平,同类元件按编号从小到大的顺序排序;有错误时,电路应输出相应提示,异常情况包括一个连接信息中包含两个或多个输入、一个连接信息中没有输入信息、一个连接信息中没有输出、一个连接信息中输入输出写反、一个输入引脚接受中来自多个不同输出的信号,如果一条输入出现了多种异常,按以上异常先后顺序为优先级,顺序靠前者优先级越高,最后输出优先级最高的异常输出,当电路输入信息中多条输入都包含异常,只处理排在最前面的异常信息。类图如下:
首先需要 Signal(信号类) 来存储每个信号的名称和电平值;一个 GetSignal(信号输入类) 负责读取输入数据并构建信号链表,供 MainCircuit(主电路类) 和 SubCircuit(子电路类) 解析电路连接关系并绑定信号,再由 CircuitComparator(排序类) 按类型和编号排序电路元件,并通过调用 Andgate、Orgate、NotOrgate、Xorgate、Xnorgate(各类门电路) 的 Output 方法 计算逻辑结果,计算完成后由 MainCircuit 和 SubCircuit 分别判断并输出有效电路元件的最终信号状态,实现整个主电路与子电路的装载与执行过程。
分析:


第四次作业(OOP4) 代码平均复杂度3.63,Decoder的Output方法复杂度22,逻辑过密风险高,需拆分复杂计算逻辑。


第五次作业(OOP5) 代码平均复杂度4.29,SetCircuit方法复杂度28,流程控制复杂,需优化信号绑定逻辑并增加注释。


第六次作业(OOP6) 代码平均复杂度3.53,InputJudge的getInput方法复杂度16,错误处理分支过多,需重构为策略模式。
3.采坑心得
第四次题目集时,由于只考虑了A(1)-1等含有括号的情况而遗漏了X1等不含括号的情况导致字符串长度与实际不符,数组越界,导致Exception in thread "main" java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 1
at java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:55)
at java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:52)
at java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:213)
at java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:210)
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
由于书写代码时的疏忽,输出重复的内容。后增加查重逻辑得以解决。

第五次题目集时,Decoder输出逻辑 Bug(试图给 OutPin赋值一个名为 Y0的字符串,但 OutPin数组期望的是引脚全名(如 M(2)1-6)。导致后续 outComponent找不到信号,或者比较信号时出错)、outComponent中逻辑缺陷(如果没有找到输出为 0的引脚,函数会没有返回值(return null),直接导致主程序崩溃)导致各种非0返回。
在Decoder: 重写 Output(),确保输出引脚名字正确,且无效时输出 "-"。GetComponent: outComponent()中 case 'M'和 case 'F'加上 null检查,并确保总有返回值。SetComponent: getSignal()最后return"0"; CircuitComparator: num()用最基础的 char遍历转数字。Main: 最后输出加 if (out != null)。解决报错。
第六次题目集时,由于子电路的输出引脚的代码风格与输入引脚一致,导致输入子电路时直接系统将输出行错认为一个连接信息中没有输出。后为InputJudge类中添加属性String out用来分辨子电路的输出引脚。后又因为MainCircuit类input方法中创建 InputJudge时使用了无参构造函数,导致 out字段为 null。随后在 ErrorOne方法中调用 str.contains(out)时,因 out为 null而抛出 NullPointerException。后在 MainCircuit.input中,将 new InputJudge()改为 new InputJudge("OUT"),确保 out不为 null解决问题。
心得:写程序前应该先去观察需求,避免输入的内容与代码差距过大导致输出错误的内容;此外,写完代码后需不断调试来避免那些逻辑缺陷。
4.改进建议
第四次题目集:拆分Decoder高复杂度方法,引入Pin类统一引脚命名,前置元件有效性校验,消除字符串解析隐患。
第五次题目集:重构SetCircuit流程控制,抽象输出格式方法,使用Optional杜绝空返回值,降低主类判断逻辑。
第六次题目集:采用责任链模式处理异常优先级,删除危险无参构造,通过类型体系区分子电路与主电路。
5.总结
本阶段三次作业集围绕面向对象程序设计展开,从基础语法到复杂系统层层递进,不仅让我的代码能力有了质的飞跃,更培养了系统的工程思维。第四次作业让我扎实掌握了类的定义、继承与多态这些核心概念;第五次作业则深入理解了类与类之间的关系,体会到了设计良好结构的重要性;第六次作业更是融合了组合模式与异常处理,打造出了一个健壮的系统。虽然中途踩过不少坑,但也让我看清了自己设计前瞻性的不足,未来我会更加注重代码的低耦合与可扩展。

浙公网安备 33010602011771号