题目集4-5以及课堂测试的总结
前言:
这三周我们完成了围绕数字电路展开的两次大作业。第四次作业仅仅进行了基础逻辑门的电路模拟,第五次作业在此基础上新增三态门、译码器、数据选择器、数据分配器等带控制引脚的复杂元件。同时我们还在课堂上进行了课堂测验,进行了对理论知识的考查。
一、所用知识点:
1.抽象类与抽象方法的设计、重构与实现
2.子类继承、方法重写与多态的核心应用
3.面向对象编程的开闭原则、单一职责原则深化实践
4.复杂元件逻辑封装
二、难度以及题量总结:
(1)数字电路模拟程序(第四次作业):
难度中等偏下,核心是基础逻辑门的封装和输入输出的解析。第一次完成花费约 6 小时,主要时间消耗在正则表达式解析复杂的引脚连接格式和循环依赖导致的空指针处理上。由于延续了电梯调度作业的面向对象设计思路,本次作业从一开始就拆分了抽象门类、具体门类、输入解析类和电路管理类,代码结构清晰,符合单一职责原则。
主要难点:解析正则表达式、解决元件循环依赖问题
(2)数字电路模拟程序(第五次作业):
难度较大,题量和逻辑复杂度显著提升。本次花费约 8 小时,其中大多数时间都是在修改原本的结构,较少时间用于扩展元件。第五次作业的作业看似只会添加了几个新元件,实际和我第四次作业的实现逻辑相差较大,为此我对原Gate类的逻辑也进行了大量修改。
主要难点:解决多输出门作为输入引脚问题
(3)课堂测试:
难度较低,考察的都是基本的理论知识,很多都是雨课堂上的原题,不过考试前没有准备充分,有部分知识点遗忘,发挥较差。
第四次作业
一、作业要求
本次作业需编程实现数字电路模拟程序,模拟与、或、非、异或、同或五种逻辑门的电平运算,按指定格式读取电路输入和引脚连接信息(以 end 结束),最终按门类型和编号排序输出有效元件的输出电平(输入无效的元件忽略)。
二、类图

分析:
1.Gate:抽象类,负责构建基本的门
2.AndGate:实现与门电平运算
3.OrGate:实现或门电平运算
4.NotGate:实现非门电平运算
5.XorGate:实现异或门电平运算
6.XnorGate:实现同或门电平运算
7.Inputread:解析输入信息,创建并连接逻辑门实例
8.Circuit:管理逻辑门,排序并输出有效元件的电平
我设计的这套数字电路模拟程序类图,整体上踩准了面向对象设计的核心方向,同时也存在一些可以打磨的细节:一方面,我有意识地用Gate抽象类搭配子类的结构落地继承与多态,还拆分出Inputread和Circuit类来拆分职责,给基础逻辑门的实现搭好了清晰的框架,甚至预留了通过扩展子类新增元件的空间,算是一次成功的面向对象实践;但是同时我对Gate类的抽象封装还不够细致,通用的引脚管理逻辑没能完全复用,解析功能也暂时和核心逻辑放在了一起,加上设计时更聚焦当下功能实现,没提前考虑复杂元件的扩展场景,命名也有少量不够精准的地方,这让我更加了解了,这次设计让我对抽象以及继承方法更加了解了。
三、代码复杂度:

优点:
1.模块化设计:设计 10 个类,每类平均 4.40 个方法,通过拆分专用类实现职责分离,符合单一职责原则。
2.基础方法体量合理:方法平均代码行数 8.23 行,多数方法无过度冗长问题,逻辑体量适中。
不足:
1.核心方法复杂度过高:Gate.judgetype()方法复杂度高达 71,逻辑分支过度堆积,维护风险高。后续应该重新调整部分逻辑,思考更好的方法。
2.嵌套层级冗余:代码块最深嵌套 8 层,平均块深度 3.39,存在过多不必要的多层嵌套。
3.整体复杂度偏高:代码平均复杂度 5.52,整体逻辑简洁性不足,后续可以尝试在分支里加return语句提前结束,降低代码复杂度。
四、思路讲解:
本代码实现主要的类有抽象类Gate类,Inputread类和Circuit类。
1.Gate 类:作为所有逻辑门的抽象父类,定义 pin 数组、connected 数组、calculating、output 等通用属性,其中 pin 数组存储连接的门,connected 数组标记引脚连接状态,calculating 用于防止循环依赖,output 记录输出电平。该类封装 checkConnected 方法校验引脚连接,通过 getOutput 方法检测循环依赖后调用子类的 computeOutput 方法,子类只需重写该方法即可实现专属电平运算,比如与门的全 1 出 1 逻辑。
点击查看代码
//核心方法getOutput()
public final int getOutput() {
if (calculating) { // 检测到循环依赖,返回异常
return -1;
}
calculating = true;
int result = computeOutput();
calculating = false;
return result;
}
abstract int computeOutput(); // 子类实现具体计算逻辑
2.Inputread 类:核心负责解析两类输入指令,一是 INPUT 开头的指令,用于创建或更新输入门;二是门连接指令,通过正则提取信息创建逻辑门并建立引脚连接。同时提供 getRepeat、getRepeatInput 方法避免重复创建逻辑门,getAllGate 方法按类型筛选逻辑门实例,为后续流程提供数据支撑。
3.Circuit 类:接收各类逻辑门数组,先通过冒泡排序将逻辑门按编号升序排列,再遍历调用 getOutput 方法获取有效电平结果,过滤掉异常值 - 1 后,格式化输出各类逻辑门的运算结果。
点击查看代码
public void show() {
for (int i = 0; i < andgate.length; i++) {
if (andgate[i].getOutput() != -1) {
System.out.println("A(" + (andgate[i].getPinNum() - 1) + ")" + andgate[i].getGno() + "-0" + ":" + andgate[i].getOutput());
}
}
for (int i = 0; i < orgate.length; i++) {
if (orgate[i].getOutput() != -1) {
System.out.println("O(" + (orgate[i].getPinNum() - 1) + ")" + orgate[i].getGno() + "-0" + ":" + orgate[i].getOutput());
}
}
for (int i = 0; i < notgate.length; i++) {
if (notgate[i].getOutput() != -1) {
System.out.println("N" + notgate[i].getGno() + "-0" + ":" + notgate[i].getOutput());
}
}
for (int i = 0; i < xorgate.length; i++) {
if (xorgate[i].getOutput() != -1) {
System.out.println("X" + xorgate[i].getGno() + "-0" + ":" + xorgate[i].getOutput());
}
}
for (int i = 0; i < xnorgate.length; i++) {
if (xnorgate[i].getOutput() != -1) {
System.out.println("Y" + xnorgate[i].getGno() + "-0" + ":" + xnorgate[i].getOutput());
}
}
}
五、踩坑心得:
1.循环依赖导致的无限递归:最初未加calculating标记,当出现 A 门输入依赖 B 门、B 门输入依赖 A 门的场景时,该程序将无限执行下去。添加caculator标记后,检测到循环依赖直接返回-1代表异常,解决了该问题。
2.Inputread 类中逻辑门重复创建:最初解析输入指令时,若 Inputread 类管理的 gate 数组中出现重名的逻辑门,会重复创建对应门实例,导致引脚连接指向错误实例、电平运算异常。新增 getRepeatInput和 getRepeat 方法,检测到重名逻辑门时不再新建实例,而是直接更新为最新的状态,解决了该问题。
六、改进建议:
1.当前代码注释占比仅 6.2%,可读性较差。后续应该多加些注释。
2.当前代码块最深嵌套达 8 层,远超合理范围。后续应该简化多层条件判断等方式,减少嵌套层数,降低代码复杂度。
第五次作业
一、作业要求:
本次作业要求在原有数字电路模拟程序基础上,新增三态门、译码器、数据选择器、数据分配器等带控制引脚的复杂逻辑元件,需扩展 Gate 抽象类以适配控制引脚特性,实现各类新增元件的电平运算逻辑,解决多输出门作为输入引脚的适配问题,同时兼容原有输入解析与电路管理流程,最终按类型和编号排序输出所有有效元件的电平结果。
二、类图:

分析
1.Gate:抽象类,所有逻辑门(含新增元件)父类,新增控制 / 多输出引脚属性,封装统一接口;
2.AndGate/OrGate/NotGate/XorGate/XnorGate:实现基础逻辑门电平运算;
3.TriStateGate:新增三态门,依控制引脚实现正常输出 / 高阻态;
4.DecoderGate:新增译码器,依地址 + 控制引脚输出对应电平;
5.MultiplexerGate:新增数据选择器,通过控制引脚选输入并输出;
6.DemultiplexerGate:新增数据分配器,依控制引脚分配输入电平;
7.Inputread:解析输入,新增复杂元件指令解析,创建并连接所有门实例;
8.Circuit:管理逻辑门,新增复杂元件排序输出逻辑,统一输出结果;
9.GateOutputPinPair:新增辅助类,管理多输出门引脚映射。
这套类图是上次设计的扩展,新增了三态门、译码器等复杂元件子类,同时强化 Gate 抽象类的控制引脚与多输出引脚管理能力,其延续了面向对象核心思路,通过 “Gate 抽象类加子类” 的结构复用原有继承和多态框架,也能通过新增子类快速扩展元件,Inputread 和 Circuit 类通过功能扩展兼容新元件,符合 “开闭原则”,但 Gate 类抽象粒度可进一步细化,部分新增元件的通用逻辑也需收拢复用;这次设计让我更深入理解 “抽象类支撑扩展”,再强化父类通用能力后,新增元件只需聚焦特有逻辑,这大幅降低了扩展成本。
三、代码复杂度:

我将代码从500行扩展至1000行(核心新增复杂元件功能),过程中有进步也有疏漏,核心情况如下:
优点:
1.复杂度优化有成效:我梳理了旧版冗余逻辑,最深块深度从8层降至6层,平均块深度从3.39压至2.46,平均复杂度也从5.52降到4.37,核心逻辑堆积问题明显缓解。
不足:
1.注释工作严重退步:旧版注释率6.2%,新版因新增逻辑,我将原先的一些变化了的逻辑删除了,后续也未补注释,率降至1.1%,后续必须补全核心注释。
2.优化仍未达标准:41的最大复杂度、6层块深度仍远超规范;分支占比仅从31.7%微降至29.9%,冗余判断未梳理,调试风险高。这些后续都应该更加优化。
四、思路讲解:
基于最新代码,为了满足新的需求,我对原类进行了大量修改,同时新增了许多功能
Gate类及子类:我给Gate抽象类新增connectedOutputPin数组,专门记录每个引脚对应的目标输出引脚,解决旧版引脚关联不清晰的问题;新增getOutputByPin方法支持按具体引脚获取输出值,适配多引脚元件需求,同时加了getSpecialOutput抽象方法作为解码器、解复用器的统一输出入口。子类实现上,让解码器和解复用器重写getSpecialOutput来实现各自的输出逻辑,多路选择器补充getOutputPinNum方法返回输出引脚编号,三态门则完善了控制引脚的读取逻辑,确保只有控制信号有效时才透传输入信号,避免无效输出。
Inputread类:我新增GateOutputPinPair内部类,把门对象、引脚编号和目标输出引脚封装在一起,解决旧版引脚信息分散的问题;扩展parseGateWithOutputPin方法,使其能解析“M(2)3-1:0”这类带目标引脚的指令,精准建立引脚间的关联。优化getOrCreateGate方法,让程序先检查是否存在同类型同编号的门,存在则直接复用,不存在再创建新实例,避免重复实例化;同时完善receiveGateOrder的逻辑,通过封装类统一处理输入输出端的门信息,确保门与门之间的连接关系准确无误。
Circuit类与Main类:我简化Circuit类的排序逻辑,把原本分散的排序代码整合为一个统一的sort方法,对所有类型的门按编号升序排列,排序后自动调用show方法输出结果,让流程更连贯;show方法适配了新增的getSpecialOutput接口,简化解码器、解复用器的输出处理。Main类作为程序入口,我保持其功能稳定,实例化Circuit时传入所有类型的门数组,确保新增的复杂元件都能被纳入排序和输出流程,与Inputread类的解析结果形成完整闭环。
五、踩坑心得:
1.数据分配器输出格式错误:最初输出无效状态时用 0 而非 -,且未按引脚编号排序输出,调整getDemuxOutput()方法的字符串拼接逻辑后解决。
2.多输出引脚门作为输入处理缺失:最初未考虑解码器、解复用器等多输出门作为输入源的场景,无法指定读取具体引脚值,导致关联门运算结果错误。我新增 connectedOutputPin 数组记录目标引脚,开发 getOutputByPin 方法按引脚取值,并在 Inputread 类封装引脚信息、扩展指令解析逻辑,精准关联多输出门的指定引脚后解决。
六、改进建议:
1.注释过少,后续核心方法 getOutput ()、getOutputByPin ()逻辑最为复杂,可以选择优先补注释
2.现在门扩展太困难,后续可以尝试使用工厂模式实现
3。当前Gate抽象类承担过多职责,最好重改该类,可以考虑加一个控制门类作为Gate类的子类
课堂测试
分析:
本次课堂测试主要考察了以下知识点:
1.Java 基础语法:标识符、关键字、数据类型、运算符、流程控制、数组、编译运行命令、注释
2.面向对象核心:封装(private、访问修饰符)、继承(extends、super)、多态(重写 / 重载)、抽象类和接口
3.类与方法细节:类结构、this/static/final/abstract 关键字、方法重写规则
4.常用类:String 的特性和用法、HashMap、Random/Arrays 工具类
5.异常与包:异常抛出、package/import 的使用
6.代码实操:改代码错误、预测程序结果、写简单类和接口
其中我主要出错在:
1.多态细节没吃透:比如父类引用指向子类对象时的方法调用(Person t = new Teacher () 调用 printValue (10)),我没搞懂多态下优先调用子类重写的方法;还有多态的前提条件判断,把 “向下转型” 也当成必要条件,其实根本不用。
2.抽象类与接口的核心区别混淆:反复错在接口能不能有构造方法、能不能定义非抽象方法,还有类实现接口用 implements、接口继承接口用 extends,这些关键规则记混了,导致多选次次错。
踩坑心得:
这次课堂测试的结果较差,核心根源在于考前准备不足且学习思路存在偏差。考前我仅对面向对象的大框架有模糊认知,没花时间深挖细节规则,比如多态的方法调用逻辑、抽象类与接口的核心区别、super 和 this 的使用边界等,都是一扫而过,导致考场上看似熟悉的知识点却频频卡壳。父类引用指向子类对象时该调用哪个方法、抽象类是否有构造方法、接口方法的默认修饰符,这些基础细节的模棱两可,直接让判断题、多选题接连出错。
更关键的是,我平时学习一直陷入上手就开始写代码,而不是先设计的误区,写代码只追求功能跑通,比如定义类、实现方法时,只要能输出结果就满足,完全没思考背后的设计逻辑:用 extends 继承时,没深究子类构造为何默认调用父类无参构造;用 implements 实现接口时,不懂接口 “完全抽象、支持多继承” 的设计初衷;写方法重写时,也忽略访问权限、返回值兼容性的硬性规则。这种只关注 “怎么写代码”,不琢磨 “为什么这么设计” 的习惯,让我面对测试中 “考规则、考逻辑” 的题目时,只能凭感觉判断,比如分析子类隐藏父类变量的取值逻辑、判断多态前提条件时,根本抓不住核心,最终导致大量失分。针对这次暴露的问题,我一定要重新学习,认真对待这些以前我认为不重要的基础知识。
总结
这三周我进行了数字电路模拟编程实践以及课堂测试。从基础逻辑门封装到复杂控制元件扩展,从功能实现到设计思维打磨,再到面向对象理论查漏补缺,这段经历让我提升了编程能力,也看清自身不足,更懂 “编程不止是实现功能,更是架构设计与逻辑梳理” 的本质。
两次数字电路作业里,我既体会到面向对象设计的价值,也踩了不少设计考量不足的坑。第四次作业实现基础逻辑门时,我拆分 Gate 抽象类、具体逻辑门类、Inputread 解析类和 Circuit 管理类,按单一职责原则搭建结构,基础功能实现和调试都很顺畅。但当时设计有明显短板:Gate 类抽象粒度不足,通用引脚管理逻辑未充分复用,judgetype () 方法分支堆积导致复杂度飙升,且没考虑后续复杂元件扩展。到第五次作业新增三态门、译码器等元件时,前期缺陷集中爆发 —— 我花 80% 时间修改 Gate 父类结构,而非专注扩展子类。直到新增 connectedOutputPin 数组管理多输出引脚、设计 GateOutputPinPair 类封装引脚关联,才解决核心问题。这让我彻底明白:优秀的面向对象设计要 “向前看”,抽象类需收拢通用逻辑并预留扩展接口,父类根基扎稳,子类扩展才能高效低耦合。
课堂测试的结果,戳中了我 “重实现、轻理论” 的痛点。测试围绕面向对象基础展开,但我在多态调用逻辑、抽象类与接口区别等知识点上频繁出错,既搞混父类引用指向子类对象的方法调用规则,又记错接口无构造方法、默认方法修饰符等细节。根源在于平时只关注 “代码能不能跑通”,忽略 “为什么这么设计”:用 extends 时没深究子类构造调用父类无参构造的底层逻辑,用 implements 时不懂接口 “完全抽象、支持多继承” 的设计初衷。这种 “知其然不知其所以然” 的学习方式,导致理论知识零散,面对 “考逻辑、考细节” 的测试只能凭感觉判断,最终失分严重。
这段经历让我明确了改进方向:一是打磨设计思维,写代码前画类图梳理结构,明确抽象类与子类职责,提前考虑扩展场景;二是优化代码质量,拆解高复杂度方法,减少嵌套层级,补全核心注释,让代码既 “能跑” 又 “好懂”;三是夯实理论基础,把面向对象核心规则牢记于心。
最后是我给老师提的建议,希望老师下次大作业前能先进行更多指导。虽然说进行指导后同学们可能自己想法会少,容易都写一样,但是哪怕是将老师给的方法自己重写一遍也是能力上的提升,对这种设计方法也会更加了解。由于这次老师是在第二次数字电路作业前才进行指导的,第一次我的设计方案有问题,第二次就及其难修改。若是第一次就使用到老师讲的观察者模式或者工厂模式一定可以轻松许多。

浙公网安备 33010602011771号