面向对象的设计第二阶段设计总结分析
前言
面向对象的设计第二阶段设计已经结束,在此时间中,我通过题目的训练,了解了许多:
- “对象思路拆解问题” 的落地能力
- Java 基本语法的 “场景化掌握”
- 代码复用与工具使用的 “工程化意识”
第四次作业
7-3 NCHUD-数字电路模拟程序-1
分数 55
作者 蔡轲
单位 南昌航空大学
数字电路是一种处理离散信号的电子电路。与处理连续变化信号(如声音、温度)的模拟电路不同,数字电路只识别和运算两种基本状态:高电平(通常表示为“1”) 和 低电平(通常表示为“0”)。这正好与二进制数制系统相对应,使得数字电路成为所有计算机和数字系统的物理实现基础。
请编程实现数字电路模拟程序,
1、电路元件
电路中包含与门、或门、非门、异或门、同或门五种元件。元件特征如下:
与门:
包含两个或多个输入引脚和一个输出引脚。所有输入引脚必须都是高电平,输出引脚才是高电平,只要有一个输入引脚为低电平,输出引脚输出低电平。
或门:
包含两个或多个输入引脚和一个输出引脚。所有输入引脚必须都是低电平,输出引脚才是低电平,只要有一个输入引脚为高电平,输出引脚输出高电平。
非门:
包含一个输入引脚和一个输出引脚。输出引脚的电平与输入引脚的电平相反,如输入为低电平,输出则为高电平。
异或门:
包含两个输入引脚和一个输出引脚。当两个输入引脚电平不一致时输出引脚输出高电平,否则输出低电平。
同或门:
包含两个输入引脚和一个输出引脚。当两个输入引脚电平一致时输出引脚输出高电平,否则输出低电平。
2、程序输入
1)元件信息:
用A、O、N、X、Y 分别用作与门、或门、非门、异或门、同或门五种元件的元件标识符。
电路中的每个与门、或门用“标识符(输入引脚数)+编号”作为其元件名。
例如:A(8)1表示一个8输入引脚的与门,O(4)2代表一个4输入引脚的或门。
电路中的每个非门、异或门、同或门用“标识符+编号”作为其元件名。
例如:X8表示一个异或门,Y4代表一个同或门,N1代表一个非门。
约束条件:
不同元件的编号可以相同,如X4、Y4。
同一电路中同种元件的编号不可重复,可以不连续
2)引脚信息:
引脚信息由“元件名-引脚号”构成,。
例如:A(8)1-2代表与门A(8)1的2号引脚。
3)电路的输入信息:
电路的输入格式:
INPUT:英文空格+输入1+”-”+输入信号1+英文空格+输入2+....+输入n+”-”+输入信号n
例如:
“INPUT: A-0 B-1 C-0”代表整个电路包括3个输入:A、B、C 分别输入0,1,0信号。
4)连接信息
引脚的连接信息格式:
[+输出引脚+英文空格+输入引脚1+。。。。+英文空格+输入引脚+]
例如:
[A A(8)1-1 A(8)1-3 X5-2]
代表信号从引脚A发送给与门A(8)1的1、3两个引脚,以及异或门X5的2号引脚。
[Y8-0 N1-1 O(4)2-3 Y2-1]
代表信号从引脚Y8-0发送给非门N1的1号引脚、或门O(4)2的3号引脚、同或门Y2的1号引脚。
约束条件:
一个输出引脚可以连接多个输入引脚,即将输出引脚的信号传给每一个输入引脚。但一个输入引脚不能连接多个输出引脚。
输出引脚不能短接在一起。
5)输入结束信息
所有输入以end为结束标志,end之后出现的内容忽略不计
3、程序输出
按照与门、或门、非门、异或门、同或门的顺序依次输出所有元件的输出引脚电平。同类元件按编号从小到大的顺序排序。
如果某个元件的引脚没有接有效输入,元件输出无法计算,程序输出结果忽略该元件
4、测试输入默认满足以下条件:
1)每个元件的输入引脚连续编号。假设元件有n个输入引脚,则其编号取值范围为[1,n],且引脚号不重复。
2)本题涉及的五种元件都只有一个输出引脚,输出引脚号默认为0。
5、后续迭代设计
数字电路模拟程序1:
基础逻辑门元件构成电路
数字电路模拟程序2(本次作业):
1、包含多输入输出的组合电路元件如数据选择器;
2、元件引脚类型除输入、输出之外,增加控制引脚,如三态门。
数字电路模拟程序3:
增加带反馈的电路、时序电路元件,如D触发器、JK触发器。
数字电路模拟程序4:
1、增加子电路;
2、增加程序异常输入的检测。
输入样例1:
在这里给出一组输入。例如:
INPUT: A-1 B-1
[A A(2)1-1]
[B A(2)1-2]
[A(2)1-0 OUT]
end
输出样例1:
在这里给出相应的输出。例如:
A(2)1-0:1
输入样例2:
在这里给出一组输入。例如:
INPUT: A-1 B-0
[A X1-1]
[B X1-2]
[X1-0 Y1-1]
[A Y1-2]
[Y1-0 OUT]
end
输出样例2:
在这里给出相应的输出。例如:
X1-0:1
Y1-0:1
输入样例3:
在这里给出一组输入。例如:
INPUT: A-1 B-1 C-1 D-0
[A A(4)1-1]
[B A(4)1-2]
[C A(4)1-3]
[D A(4)1-4]
[A(4)1-0 OUT]
end
输出样例3:
在这里给出相应的输出。例如:
A(4)1-0:0
处理方法
我的处理方法如下:
- 问题拆解:按功能拆分为「元件管理」「输入解析」「元件逻辑」「引脚信号」4 个子模块,各模块单一职责。
- 面向对象建模:抽象
Component(元件)、Pin(引脚)父类,派生具体子类(如A与门、Pin_in输入引脚),工具类ComponentManage管元件、Input管输入解析。 - 逻辑流程:解析输入→创建元件 + 连接引脚→按依赖计算元件输出→按规定顺序排序输出。
- 边界防护:处理空值、数组越界、格式错误,用
2表示无效电平,跳过无效元件 / 引脚。 - 适配需求:遵循引脚编号规则(输入 1~n、输出 0),按题目要求排序输出,适配 5 类基础门逻辑。
类图设计:

虽然我完成了大部分的测试但我的最后一个测试点却没有实现,我也向他人请教,但他们们也不知道,所以应该是设计还是有缺陷
再看一下代码分析:
Metrics Details For File 'Main.java'
Parameter Value
========= =====
Project Directory D:\java\daima\Main\src\Main
Project Name
Checkpoint Name Baseline
File Name Main.java
Lines 940
Statements 567
Percent Branch Statements 28.6
Method Call Statements 203
Percent Lines with Comments 7.3
Classes and Interfaces 13
Methods per Class 4.85
Average Statements per Method 8.65
Line Number of Most Complex Method 333
Name of Most Complex Method Input.create_component()
Maximum Complexity 63
Line Number of Deepest Block 817
Maximum Block Depth 9+
Average Block Depth 3.90
Average Complexity 3.44
Most Complex Methods in 19 Class(es): Complexity, Statements, Max Depth, Calls
A().get_pin() 1, 1, 4, 0
A().out() 5, 11, 6, 4
A().set_out() 2, 4, 5, 0
A().set_pin() 2, 2, 4, 0
A.A() 7, 1, 4, 0
Component.Component() 1, 2, 3, 0
Component.get_pin() 1, 1, 3, 0
Component.getMax() 1, 1, 3, 0
Component.getName() 1, 1, 3, 0
Component.set_out() 1, 1, 3, 0
Component.setMax() 1, 1, 3, 0
Component.setName() 1, 1, 3, 0
ComponentManage.addComponent() 2, 2, 3, 1
ComponentManage.getComponent() 1, 1, 2, 1
ComponentManage.removeComponent() 1, 1, 2, 1
in_put().get_out() 1, 1, 9, 0
in_put().out() 1, 1, 9, 0
in_put().set_out() 1, 1, 9, 0
in_put.in_put() 1, 1, 9, 0
Input.create_component() 63, 140, 6, 69
Input.extractNumberFromParentheses() 4, 10, 4, 5
Input.getInput() 1, 1, 2, 0
Input.handle_pin() 9, 14, 5, 1
Input.Input() 1, 2, 2, 1
Input.isAndGate() 1, 2, 2, 2
Input.isNotGate() 1, 2, 2, 2
Input.isOrGate() 1, 2, 2, 2
Input.isXnorGate() 1, 2, 2, 2
Input.isXorGate() 1, 2, 2, 2
Input.setInput() 1, 2, 2, 1
Main.main() 5, 11, 3, 6
N().get_pin() 1, 1, 6, 0
N().out() 4, 7, 7, 3
N().set_out() 2, 4, 7, 0
N().set_pin() 2, 2, 6, 0
N.N() 6, 1, 6, 0
O().get_pin() 1, 1, 5, 0
O().out() 5, 11, 7, 4
O().set_out() 2, 4, 6, 0
O().set_pin() 2, 2, 5, 0
O.O() 7, 1, 5, 0
Pin.getLevel() 1, 1, 9, 0
Pin.Pin() 1, 1, 9, 0
Pin.setLevel() 1, 1, 9, 0
Pin_in.Pin_in() 1, 1, 9, 1
Pin_in.push_in() 1, 1, 9, 0
Pin_in.set_in() 1, 1, 9, 0
Pin_out.Pin_out() 1, 2, 9, 1
Pin_out.set_out() 1, 1, 9, 1
X().get_pin() 1, 1, 7, 0
X().out() 7, 14, 8, 6
X().set_out() 2, 4, 8, 0
X().set_pin() 2, 2, 7, 0
X.X() 9, 1, 7, 0
Y().get_pin() 1, 1, 8, 0
Y().out() 7, 14, 9, 6
Y().set_out() 2, 4, 9, 0
Y().set_pin() 2, 2, 8, 0
Y.Y() 9, 1, 8, 0
Block Depth Statements
0 52
1 61
2 91
3 63
4 59
5 74
6 76
7 33
8 38
9+ 20

可以发现Input.create_component() 方法严重 “臃肿”和代码整体的嵌套层级过深的问题
这是因为我的设计失误,其实也可以对input进行拆分,create_component() 方法承担了过多职责,这才导致臃肿
优化优先级:先拆分create_component()为多个小方法,再减少逻辑嵌套层级,最后补充关键注释;
优化目标:将核心方法的复杂度降到 10 以下,最大块深度控制在 5 以内,提升代码的可读性和可维护性。
踩坑心得
因为我并没有完全做出来,但还是可以写一写的,首先要注意这个顺序是乱序的,不然会有点无法通过,再者要处理好输入,输入会出现与元件同名的情况
第四次作业
7-3 NCHUD-数字电路模拟程序-2
分数 50
作者 蔡轲
单位 南昌航空大学
数字电路是一种处理离散信号的电子电路。与处理连续变化信号(如声音、温度)的模拟电路不同,
数字电路只识别和运算两种基本状态:高电平(通常表示为“1”) 和 低电平(通常表示为“0”)。
这正好与二进制数制系统相对应,使得数字电路成为所有计算机和数字系统的物理实现基础。
请编程实现数字电路模拟程序。
以下内容中,首行用#号标注的为本次新增的题目要求,其余内容与“数字电路模拟程序-1”相同。
**
**
1、电路元件
电路中包含与门、或门、非门、异或门、同或门、三态门、译码器、数据选择器、数据分配器九种元件。元件特征如下:
与门:
包含两个或多个输入引脚和一个输出引脚。所有输入引脚必须都是高电平,输出引脚才是高电平,只要有一个输入引脚为低电平,输出引脚输出低电平。
或门:
包含两个或多个输入引脚和一个输出引脚。所有输入引脚必须都是低电平,输出引脚才是低电平,只要有一个输入引脚为高电平,输出引脚输出高电平。
非门:
包含一个输入引脚和一个输出引脚。输出引脚的电平与输入引脚的电平相反,如输入为低电平,输出则为高电平。
异或门:
包含两个输入引脚和一个输出引脚。当两个输入引脚电平不一致时输出引脚输出高电平,否则输出低电平。
同或门:
包含两个输入引脚和一个输出引脚。当两个输入引脚电平一致时输出引脚输出高电平,否则输出低电平。
#三态门:
三态门的作用类似于电路中的开关。包含一个输入引脚、一个输入控制引脚、一个输出引脚。当控制引脚为高电平时,三态门输入输出之间导通,输出电平等于输入电平;当控制引脚为低电平时,三态门输入输出之间呈现高阻态(类似开关断开),输出为无效状态。
#译码器:
译码器的作用是讲输入的编码转换为一路有效信号。一个译码器包含两个或多个输入引脚(如图中的A2\A1\A0)、三个控制引脚(如图中的S3\S2\S1)、4个或多个输出引脚(如图中的Y7~Y0)。根据输入输出的数量有2-4线译码器、3-8线译码器等。
当控制引脚当S1 =1,S2 +S3 =0时,译码器正常工作,输出引脚只有一个输出信号0,其余输出为1;哪个引脚输出0由输入引脚的编码决定,例如:图中的3-8线译码器三个输入引脚信号的编码与输出引脚的编码对应,A2\A1\A0输入000时,Y0输出0,其余输出1;A2\A1\A0输入001时,Y1输出0,其余输出1;依次类推。
控制引脚不满足S1 =1,S2 +S3 =0时,译码器处于无效状态,所有输出为无效值。
#数据选择器:
数据选择器的作用是从多路输入信号中选择一个,并将其信号直接送往唯一的输出端,选择哪一路输入信号由控制端决定。如图所示控制端有两个则输入端有4个,S1\S0是两个控制端,D3D0是输入端,S1\S0的4种信号组合00、01、10、11分别选择D3D0其中一路输入。如S1S0=00,则Y=D0;S1S0=01,则Y=D1;S1S0=10,则Y=D2;S1S0=11,则Y=D3
根据输入引脚数量的不同有二选一数据选择器(1个控制端)、四选一数据选择器(2个控制端)、八选一数据选择器(3个控制端)等
#数据分配器:
数据分配器的作用与数据选择器正好相反,是将唯一的一路输入信号输出到多路输出引脚的其中之一,选择哪一路输出引脚输出由控制端决定。如图所示控制端有两个AB,输出端有4个W0\W1\W2\W3,D是输入端,AB的4种信号组合00、01、10、11分别选择W3~W0其中一路输出,其他三路输出为无效状态。如AB=00,则W0=D;AB=01,则W1=D;AB=10,则W2=D;AB=11,则W3=D。
根据输出引脚数量的不同有二路数据分配器(1个控制端)、四路数据分配器(2个控制端)、八路数据分配器(3个控制端)等
2、程序输入
1)#元件信息:
用A、O、N、X、Y、S 、M、Z、F分别用作
与门、或门、非门、异或门、同或门、
三态门、译码器、数据选择器、数据分配器九种元件的元件标识符。
电路中的每个与门、或门用“标识符(输入引脚数)+编号”作为其元件名。
例如:A(8)1表示一个8输入引脚的与门,O(4)2代表一个4输入引脚的或门。
电路中的每个非门、异或门、同或门用“标识符+编号”作为其元件名。
例如:X8表示一个异或门,Y4代表一个同或门,N1代表一个非门。
#电路中的数据选择器、数据分配器用“标识符(控制引脚数)+编号”作为其元件名。
例如:Z(2)2代表一个四选一数据选择器,F(3)2代表一个8路数据分配器。
译码器用“标识符(输入引脚数)+编号”作为其元件名。
例如:M(3)1表示一个3-8线译码器。
约束条件:
不同元件的编号可以相同,如X4、Y4。
同一电路中同种元件的编号不可重复,可以不连续
2)#引脚信息:
引脚信息由“元件名-引脚号”构成。
例如:A(8)1-2代表与门A(8)1的2号引脚。
#含控制引脚的元件如本次添加的所有元件,按控制-输入-输出的顺序排序,
每种类型的引脚按编号从小到大的顺序排序,
例如3-8线译码器M(3)1包含3个输入引脚、3个控制引脚、8个输出引脚,
M(3)1-0/1/2对应控制引脚S1/S2/S3,
M(3)1-3/4/5对应输入引脚A0/A1/A2,
M(3)1-6/7/8/9/10/11/12/13对应输出引脚Y0\~Y7。
又如三态门的三个引脚,0号引脚为控制端、1号引脚为输入端、2号引脚为输出端。
3)电路的输入信息:
电路的输入格式:
INPUT:英文空格+输入1+”-”+输入信号1+英文空格+输入2+....+输入n+”-”+输入信号n
例如:
“INPUT: A-0 B-1 C-0”
代表整个电路包括3个输入:A、B、C 分别输入0,1,0信号。
4)连接信息
引脚的连接信息格式:
[输出引脚+英文空格+输入引脚1+。。。。+英文空格+输入引脚]
例如:
[A A(8)1-1 A(8)1-3 X5-2]
代表信号从引脚A发送给与门A(8)1的1、3两个引脚,以及异或门X5的2号引脚。
[Y8-0 N1-1 O(4)2-3 Y2-1]
代表信号从引脚Y8-0发送给非门N1的1号引脚、或门O(4)2的3号引脚、同或门Y2的1号引脚。
约束条件:
一个输出引脚可以连接多个输入引脚,即将输出引脚的信号传给每一个输入引脚。但一个输入引脚不能连接多个输出引脚。
输出引脚不能短接在一起。
5)输入结束信息
所有输入以end为结束标志,end之后出现的内容忽略不计
3、#程序输出
按照与门、或门、非门、异或门、同或门、三态门、译码器、数据选择器、数据分配器的顺序依次输出所有元件的输出引脚电平。
同类元件按编号从小到大的顺序排序。
#如果某个元件的引脚没有接有效输入、输入输出之间断开(如三态门)或控制引脚输入无效,元件输出无效,程序输出忽略该元件。
#译码器不输出引脚电平,输出其输出为0的引脚的编号。如“M(3)1:3”代表译码器M3的输出引脚Y3输出0,其他引脚输出1。
#数据分配器按引脚编号从小到大的顺序输出所有输出引脚的信号,无效状态引脚输出“-”。
如“F(2)1:--0-”代表分配器F1的输出引脚W2输出0信号,其他三个引脚为无效状态。
4、测试输入默认满足以下条件:
1)每个元件的输入引脚连续编号。假设元件有n个输入引脚,则其编号取值范围为\[1,n\],且引脚号不重复。
2)本题涉及的五种元件都只有一个输出引脚,输出引脚号默认为0。
5、本系列题目的迭代设计
数字电路模拟程序1:
基础逻辑门元件构成电路
数字电路模拟程序2(本次作业):
1、包含多输入输出的组合电路元件如数据选择器;
2、元件引脚类型除输入、输出之外,增加控制引脚,如三态门。
数字电路模拟程序3:
增加带反馈的电路、时序电路元件,如D触发器、JK触发器。
数字电路模拟程序4:
1、增加子电路;
2、增加程序异常输入的检测。
输入样例1:
在这里给出一组输入。例如:
INPUT: A-1 B-1
[A A(2)1-1]
[B A(2)1-2]
end
输出样例1:
在这里给出相应的输出。例如:
A(2)1-0:1
输入样例2:
在这里给出一组输入。例如:
INPUT: A-1 B-0
[A X1-1]
[B X1-2]
[X1-0 Y1-1]
[A Y1-2]
end
输出样例2:
在这里给出相应的输出。例如:
X1-0:1
Y1-0:1
这次作业对题目进行了修改,但大体没有动,所以我的思路也没用很大的改变,但对输入输出的处理要进行修改,使其适配这次的题目
处理方法
- 处理方法延续了 “4 大模块拆解 + 面向对象建模” 的核心思路,同时覆盖了扩展元件的类型识别和逻辑实现。
- 逻辑流程保持 “解析→创建→计算→输出” 的步骤,边界防护新增了引脚冲突、扩展元件格式匹配等场景。
- 适配需求部分结合扩展元件的特性,补充了专属引脚规则和输出排序顺序,确保整体方案满足复杂电路的模拟需求。
但我这次还是没有实现完整的问题,所以我的代码水平还应该提高,这次的思路,还是继承于上次,毕竟如果大规模的修改会来不及,本星期我还有其他的事情,所以思路就没改了,但其中的逻辑还是进行了修改,那么还是先看代码分析
Metrics Details For File 'Main.java'
Parameter Value
========= =====
Project Directory D:\java\daima\Main\src\Main
Project Name fd
Checkpoint Name Baseline
File Name Main.java
Lines 1,363
Statements 883
Percent Branch Statements 24.2
Method Call Statements 328
Percent Lines with Comments 5.8
Classes and Interfaces 16
Methods per Class 6.94
Average Statements per Method 6.64
Line Number of Most Complex Method 601
Name of Most Complex Method Input.create_component()
Maximum Complexity 99
Line Number of Deepest Block 615
Maximum Block Depth 9+
Average Block Depth 6.67
Average Complexity 3.49
Most Complex Methods in 23 Class(es): Complexity, Statements, Max Depth, Calls
A().get_pin() 1, 1, 3, 1
A().get_pin() 1, 1, 3, 0
A().out() 5, 12, 5, 4
A().print_self() 1, 1, 3, 1
A().set_out() 2, 4, 4, 0
A().set_pin() 3, 4, 3, 1
A.A() 8, 1, 3, 1
Component.Component() 1, 2, 2, 0
Component.get_pin() 1, 1, 2, 0
Component.getMax() 1, 1, 2, 0
Component.getName() 1, 1, 2, 0
Component.set_out() 1, 1, 2, 0
Component.setMax() 1, 1, 2, 0
Component.setName() 1, 1, 2, 0
ComponentManage.addComponent() 2, 2, 9, 1
ComponentManage.getComponent() 1, 1, 8, 1
ComponentManage.removeComponent() 1, 1, 8, 1
F.F() 1, 1, 8, 1
F.get_pin() 1, 1, 8, 1
F.get_pin() 1, 1, 8, 0
F.out() 4, 10, 10, 2
F.print_self() 4, 7, 10, 4
F.set_out() 3, 6, 10, 1
F.set_pin() 3, 4, 8, 1
in_put().get_out() 1, 1, 8, 0
in_put().out() 1, 1, 8, 0
in_put().out() 1, 1, 8, 0
in_put().print_self() 1, 1, 8, 0
in_put().set_out() 1, 1, 8, 0
in_put.in_put() 1, 1, 8, 0
Input.create_component() 99, 244, 11, 126
Input.extractNumberFromParentheses() 4, 10, 9, 5
Input.getInput() 1, 1, 7, 0
Input.handle_pin() 13, 22, 10, 1
Input.Input() 1, 2, 7, 1
Input.isAndGate() 1, 2, 7, 2
Input.isLUT() 1, 2, 7, 2
Input.isMultiplexer() 1, 2, 7, 2
Input.isNotGate() 1, 2, 7, 2
Input.isOrGate() 1, 2, 7, 2
Input.isROM() 1, 2, 7, 2
Input.isSelector() 1, 2, 7, 2
Input.isXnorGate() 1, 2, 7, 2
Input.isXorGate() 1, 2, 7, 2
Input.setInput() 1, 2, 7, 1
Main.main() 5, 11, 4, 6
N().get_pin() 1, 1, 5, 1
N().get_pin() 1, 1, 5, 0
N().out() 4, 8, 6, 3
N().print_self() 1, 1, 5, 1
N().set_out() 2, 4, 6, 0
N().set_pin() 3, 4, 5, 1
N.N() 7, 1, 5, 1
N.outputAllComponentsInOrder() 15, 45, 6, 32
N.outputComponentsByType() 14, 25, 6, 1
O().get_pin() 1, 1, 4, 1
O().get_pin() 1, 1, 4, 0
O().out() 5, 12, 6, 4
O().print_self() 1, 1, 4, 1
O().set_out() 2, 4, 5, 0
O().set_pin() 3, 4, 4, 1
O.getComponentsGroupedByType() 16, 42, 5, 27
O.getInstance() 1, 1, 3, 0
O.O() 8, 1, 4, 1
Pin.getLevel() 1, 1, 8, 0
Pin.Pin() 1, 1, 8, 0
Pin.setLevel() 1, 1, 8, 0
Pin_in.get_index() 1, 1, 8, 0
Pin_in.Pin_in() 1, 1, 8, 1
Pin_in.push_in() 1, 1, 8, 0
Pin_in.set_in() 1, 1, 8, 0
Pin_in.set_index() 1, 1, 8, 0
Pin_out.Pin_out() 1, 2, 8, 1
Pin_out.set_out() 1, 1, 8, 1
S().get_pin() 1, 1, 9, 1
S().get_pin() 1, 1, 9, 0
S().out() 5, 14, 10, 6
S().print_self() 1, 1, 9, 1
S().set_out() 1, 3, 9, 0
S().set_pin() 3, 4, 9, 1
S.get_pin() 1, 1, 8, 1
S.get_pin() 1, 1, 8, 0
S.M() 1, 1, 8, 1
S.out() 7, 15, 10, 6
S.print_self() 2, 4, 9, 1
S.S() 7, 1, 9, 1
S.set_out() 3, 5, 10, 1
S.set_pin() 3, 4, 8, 1
X().get_pin() 1, 1, 6, 1
X().get_pin() 1, 1, 6, 0
X().out() 7, 16, 7, 6
X().print_self() 1, 1, 6, 1
X().set_out() 2, 4, 7, 0
X().set_pin() 3, 4, 6, 1
X.allComponents.sort(() 3, 5, 5, 3
X.X() 10, 1, 6, 1
Y().get_pin() 1, 1, 7, 1
Y().get_pin() 1, 1, 7, 0
Y().out() 7, 16, 8, 6
Y().print_self() 1, 1, 7, 1
Y().set_out() 2, 4, 8, 0
Y().set_pin() 3, 4, 7, 1
Y.getComponentCount() 1, 1, 6, 1
Y.Y() 10, 1, 7, 1
Z.get_pin() 1, 1, 8, 2
Z.get_pin() 1, 1, 8, 0
Z.out() 4, 10, 10, 5
Z.print_self() 1, 1, 8, 1
Z.set_out() 1, 3, 8, 0
Z.set_pin() 3, 4, 8, 1
Z.Z() 1, 1, 8, 1
Block Depth Statements
0 11
1 17
2 25
3 51
4 83
5 81
6 83
7 125
8 99
9+ 308

- 代码的核心问题是
Input.create_component()方法的职责过度集中,以及逻辑嵌套层级过深,这是前期设计时职责划分不合理导致的; - 优化的核心思路是按职责拆分方法,通过设计模式简化嵌套逻辑,再补充注释提升可读性;
- 优化后可将核心方法的复杂度和块深度控制在合理阈值内,显著提升代码的可维护性和扩展性。
踩坑心得
因为这次也没有完全写出来,所以我也就不分享什么踩坑心得了,但还是提一提我的思路,首先我们还是要了解题意,可以将学到的各种方法运用于此。虽然题目很难但是我们也要尽力去尝试,只有尝试了后才能发现自己的不足和问题,进行改进。
总结
在面向对象设计第二阶段的两次数字电路模拟程序开发中,我完成了从基础逻辑门到扩展组合电路元件的功能迭代实现,虽未完全攻克所有测试场景,但在问题拆解、面向对象建模和工程化实践上积累了宝贵经验,也清晰定位了自身存在的不足。以下是本阶段的详细总结:
一、阶段核心成果
- 建立了可扩展的电路模拟框架延续 “元件管理、输入解析、元件逻辑、引脚信号” 四大模块的拆分思路,抽象出
Component(元件)和Pin(引脚)核心父类,派生基础逻辑门(A/O/N/X/Y)和扩展元件(S/M/Z/F)等子类,通过ComponentManage工具类实现元件的注册、查找与排序,Input类处理输入解析与引脚连接,形成了职责清晰的面向对象架构。该框架支持新增元件时仅需继承父类实现抽象方法,无需修改核心框架,为后续迭代奠定了基础。 - 实现了多类电路元件的核心逻辑成功适配基础逻辑门(与、或、非、异或、同或)的电平计算逻辑,同时完成扩展元件(三态门、译码器、数据选择器、数据分配器)的功能开发,包括控制引脚的信号处理、多输入输出的逻辑运算,以及不同元件的专属输出规则(如译码器输出有效引脚编号、数据分配器区分有效 / 无效输出)。
- 构建了基础的边界防护机制针对空值、数组越界、格式错误等异常场景,设计了无效电平标识(用 “2” 表示未初始化 / 无效信号)、引脚冲突检测(提示 “线路短接”)、无效元件跳过等防护逻辑,提升了程序的健壮性
二、问题根源分析
- 前期设计缺乏精细化规划开发前未充分梳理核心方法的职责边界,未对复杂功能进行更细粒度的拆分(如将
create_component()拆分为指令清洗、类型识别、元件创建等独立子方法),仅追求 “功能实现” 而忽视 “结构优化”,导致代码架构先天存在缺陷。 - 设计模式应用不足面对大量元件类型的判断逻辑,未采用工厂模式、策略模式等设计模式简化代码,而是依赖传统的
if-else if嵌套,导致代码复杂度和嵌套层级居高不下,难以扩展和调试。 - 时间管理与优先级把控不当第二次作业迭代时,因兼顾其他事务,未能对第一次作业中暴露的
create_component()臃肿问题进行彻底重构,仅在原有框架上修改逻辑,导致问题积累加剧,最终影响功能实现的完整性。 - 需求细节挖掘不够深入对扩展元件的引脚排序规则、输出格式要求等细节理解不够透彻,未针对特殊场景(如输入与元件同名、控制引脚无效时的元件状态)设计专门的处理逻辑,导致程序适配性不足。
三、后续改进计划
- 重构核心方法,拆分过度集中的职责按优化优先级,将
Input.create_component()拆分为splitInputCommand()(指令拆分与清洗)、identifyComponentType()(元件类型识别)、createComponentInstance()(元件实例化,采用工厂模式)、connectComponentPins()(引脚连接)等单一职责子方法,目标将各方法复杂度控制在 10 以下。 - 简化逻辑嵌套,引入设计模式优化架构用策略模式替代元件类型判断的
if-else if嵌套,为每种元件设计专属的处理策略类,通过工厂类动态获取策略实例;采用 “提前返回” 替代多层else嵌套,将最大块深度控制在 5 以内,提升代码可读性。 - 规范编码习惯,提升工程化水平补充关键注释(方法级注释说明职责与参数,行级注释解释复杂逻辑),将注释覆盖率提升至 20% 以上;统一命名规范,明确变量与方法的语义,增强代码的可维护性。
- 强化需求分析,完善边缘场景处理开发前逐字梳理题目要求,绘制元件引脚规则、信号传递流程的示意图,确保对需求细节的精准把握;针对未攻克的测试场景,单独搭建最小测试用例,定位逻辑疏漏并补充处理逻辑。
- 合理规划开发时间,优先解决架构缺陷后续迭代中,优先重构现有代码的结构性问题,再进行新功能开发,避免 “带病迭代”;合理分配时间,预留充足的调试周期,确保功能实现的完整性。
五、阶段感悟
本阶段的开发让我深刻认识到:“能运行的代码不等于优秀的代码”,良好的前期设计、清晰的职责划分和规范的编码习惯,远比后期修补更为重要。面向对象设计的核心不仅是 “封装、继承、多态” 的语法应用,更在于通过合理的模块拆分和设计模式,实现代码的高内聚、低耦合。虽然两次作业均未完全达标,但暴露的问题让我明确了后续的提升方向。未来我将重点强化架构设计能力和工程化思维,在追求功能实现的同时,更注重代码的可读性、可维护性和扩展性,逐步提升自身的软件开发水平

浙公网安备 33010602011771号