面向对象设计与构造 ---- 第二单元总结

一、前言
面向对象课程的第二单元已经结束,本单元围绕数字电路仿真系统展开三次递进式迭代作业,依次完成数字电路模拟程序 1、数字电路模拟程序 2、数字电路模拟程序 3 的开发迭代,完整覆盖基础组合逻辑电路、带控制引脚复合器件电路、模块化子电路与拓扑异常检测电路三大开发阶段,完美复刻工业级小型仿真软件的迭代开发流程。三次作业题量循序渐进、难度阶梯式提升,从最初仅实现五类基础逻辑门的电平运算,到新增四类带控制引脚的复合电路元件、适配多格式差异化输出,最终落地子电路封装复用、全局电路拓扑非法校验、分层架构解耦等高阶工程功能。

从代码体量与开发难度来看,第一次作业核心有效代码约 320 行,仅考察基础面向对象建模、信号单向传递、简单电路运算;第二次作业代码扩充至 450 行,新增引脚分段管理、多类型元件差异化运算、特殊无效状态过滤、多格式输出逻辑,分支复杂度大幅提升;第四次作业代码规模突破 700 行,新增子电路独立模块、全局异常检测体系、多层工具类拆分、拓扑信号分层驱动,对代码规范性、鲁棒性、可拓展性提出极高要求。

本单元作业无复杂算法逻辑,核心考察抽象与多态落地、单一职责设计原则、分层解耦架构、防御性编程、复杂文本解析、拓扑信号迭代收敛等面向对象核心工程能力。相较于第一单元航空器配载系统的静态数据建模,本单元更侧重动态数据流转、组件化协同工作、模块复用、异常容错处理。通过三轮迭代开发,我彻底摒弃了 “功能优先、结构随意” 的新手编程思维,建立起先架构、后编码、重规范、可迭代的工程开发思维,深刻理解了抽象统一规范、子类差异化实现、分层隔离变化的面向对象核心精髓,为本阶段课程学习打下坚实的工程实践基础。

二、设计与分析
本章节将结合SourceMonitor 代码度量报表、PowerDesigner 类图,逐一对三次迭代作业的源码架构、设计思路、复杂度、核心亮点与设计缺陷进行深度剖析,全程结合代码结构、数据流转、测试数据展开分析,做到有图有据、详实具体。
前置:统一复杂度指标释义
全文代码质量分析统一采用 SourceMonitor 五大核心度量指标,统一释义:
1 v (G) 圈复杂度:方法独立执行路径总数,分支、循环越多数值越高,代表测试覆盖难度越大;
2 ev (G) 本质复杂度:衡量代码嵌套、冗余分支程度,优质工程代码单方法 ev (G)≤3;
3 iv (G) 设计复杂度:方法依赖外部类、全局容器的耦合程度,数值越高耦合越强、可维护性越差;
4 WMC 类总圈复杂度:单个类所有方法圈复杂度总和,代表类的业务承载体量;
5 OCavg 类平均圈复杂度:类总复杂度 / 方法总数,单一职责达标类 OCavg 普遍小于 3。
第一次作业:数字电路模拟程序 1(基础五类逻辑门电路)
作业要求
本次作业为数字电路仿真系统的初代基础版本,是后续所有迭代开发的底层基石。需求核心为实现与门、或门、非门、异或门、同或门五类基础逻辑门的仿真运算,所有元件仅含输入引脚与唯一 0 号输出引脚,无控制引脚、无多路输出;支持全局 INPUT 初始电平输入、单层引脚互连拓扑、信号迭代收敛运算;严格按照固定顺序、编号升序输出有效元件电平,自动忽略输入不全、无法运算的无效元件。
设计思路
本次作业采用极简三层架构,以抽象类为核心实现多态调度,整体结构扁平清晰,严格遵循单一职责原则:
1 Pin 引脚底层类
作为全局最小信号存储单元,仅维护核心属性int v,默认值 - 1 代表无效电平,0、1 为合法高低电平,无冗余业务逻辑,纯粹承担数据载体职责,统一全局引脚信号存储规范。
2 Gate 抽象父类 + 五类门实体子类
搭建整套电路的核心继承体系,抽象 Gate 父类统一封装所有电路元件的公共属性:元件名称 name、输入引脚集合 in、输出电平 out;定义抽象run()运算方法,强制所有子类实现专属运算逻辑,完美落地继承复用、多态差异化执行的核心特性。
AndGate、OrGate:适配多输入引脚特性,遍历全部输入引脚电平,根据与、或逻辑完成全局校验运算;
NotGate、XorGate、XnorGate:固定输入引脚数量,读取指定引脚电平,完成单路、双路逻辑运算。
3 全局调度核心逻辑
独立实现信号推送、元件创建、输入解析、结果排序打印逻辑,维护全局引脚信号映射、元件集合,通过循环迭代推送引脚信号,直至全局电平稳定收敛后,统一批量执行所有门电路运算,最后按规则排序过滤输出。
本次设计最大亮点为统一抽象调度,所有元件无需区分类型,统一通过父类引用调用 run 方法,极大简化了电路整体运算流程,避免了冗余的类型判断代码。同时严格遵循题目输出规则,对无效输入、引脚缺失的元件自动过滤,保证输出结果合规准确。
复杂度分析(SourceMonitor)

屏幕截图 2026-06-24 194339

屏幕截图 2026-06-24 194333

本次作业代码总行数 326 行,有效代码 298 行,整体结构扁平、嵌套极少。
1 核心方法Gate.run()子类实现平均 ev (G)=1.8,无多层嵌套 if-else,分支逻辑极简;
2 信号推送方法 v (G)=3,仅包含信号迭代、收敛判断基础循环逻辑;
3 整体 OCavg=2.1,所有类均满足单一职责,无巨型上帝类;
4 唯一高复杂度点位为元件名称解析方法,v (G)=4,需要区分多输入门、基础门两类命名规则,存在少量分支判断。
解读与心得
初代代码整体设计简洁、耦合度低,完全适配基础电路仿真需求。本次开发最大的收获是理解了抽象类与多态的工程价值:将所有元件的公共属性、公共行为抽象统一,差异化的运算逻辑交由子类实现,后续新增元件仅需新增子类,无需修改核心调度代码,初步体会到开闭原则的优势。
同时也暴露了初代设计的短板:所有信号推送、输入解析逻辑耦合在核心调度类中,未拆分独立工具类;无专门的信号有效性校验模块,边界条件处理简陋,仅能适配题目合法输入,无防御性容错能力,为后续迭代重构埋下优化空间。
类图展示

屏幕截图 2026-06-24 195138

第二次作业:数字电路模拟程序 2(九类复合元件 + 控制引脚电路)
作业要求
本次作业在初代基础上全面功能升级,属于难度跨度最大的一次迭代,题目难度标注为困难。在原有五类基础门之上,新增三态门、译码器、数据选择器、数据分配器四类复合电路元件,元件总数扩充至九类;新增控制引脚、引脚分段编号规则,所有复合元件严格按照「控制引脚 - 输入引脚 - 输出引脚」分段排序;适配九类元件全新命名规则;新增高阻无效状态、多路输出、编码译码、引脚选中输出等复杂逻辑;同时配套多格式差异化输出规则,不同元件对应完全不同的输出样式,无效控制、引脚缺失、电路断开均需过滤输出。
设计思路
本次作业在初代架构基础上拓展升级,保留核心抽象体系,仅新增子类、拓展业务逻辑,不改动顶层调度框架,完美契合开闭原则:
1 继承原有 Pin、Gate 核心体系,保证底层信号、基础门逻辑完全复用,避免重复开发;
2 新增四类复合元件子类:TriStateGate 三态门、Decoder 译码器、Multiplexer 数据选择器、Demultiplexer 数据分配器,各自独立重写 eval 运算方法,封装专属硬件逻辑;
3 实现引脚分段解析逻辑,严格遵循题目固定引脚编号规则:三态门 0 控 1 入 2 出、译码器前 3 位为控制引脚、后续依次为输入、输出引脚,彻底区分控制引脚与普通输入引脚;
4 重构输出模块,新增多分支差异化输出逻辑:基础门输出电平、译码器输出有效引脚编号、数据分配器拼接多路状态字符串、三态门过滤高阻无效状态;
5 强化无效状态判定:除引脚缺失外,新增控制引脚无效、电路断开、译码器使能不达标、高阻态等多重无效过滤规则。
本次设计的核心优化点在于逻辑内聚,每一类元件的专属运算、引脚读取、有效性判断逻辑全部封装在对应子类内部,顶层调度类无需感知各类元件的复杂规则,仅需统一调用 eval 方法,实现了变化隔离,极大降低了代码耦合度。
复杂度分析(SourceMonitor)

屏幕截图 2026-06-24 194441

屏幕截图 2026-06-24 194432

本次作业代码总行数 462 行,有效代码 425 行,核心复杂度集中在复合元件运算与差异化输出模块:
1 Decoder 译码器运算方法 ev (G)=4、v (G)=5,需要多重校验控制引脚条件、循环读取输入编码、匹配输出引脚,分支逻辑较多;
2 Demultiplexer 数据分配器输出拼接方法 v (G)=6,需要遍历所有输出引脚、区分有效 / 无效状态、拼接格式化字符串,循环嵌套较多;
3 输出排序打印方法 ev (G)=5、v (G)=9,需要按九类固定顺序、同类编号升序排序,同时区分四种输出格式,分支繁杂;
4 整体 OCavg=2.8,虽复杂度有所提升,但无病态嵌套,代码结构依然规范。
解读与心得
本次迭代让我深刻理解了面向对象多态的工程优势。面对九类元件、数十条差异化规则,若采用面向过程编程,代码会充斥大量类型判断、分支嵌套,臃肿且难以维护;而通过抽象父类 + 子类差异化实现的架构,完美化解了多类型复杂逻辑的兼容问题。
同时本次开发也暴露了我的编码短板:大量硬件规则魔法数字(引脚编号、控制条件、排序序号)硬编码在代码中,可维护性差;差异化输出逻辑集中在打印模块,分支过于密集,代码可读性有待提升;边界无效场景校验不够完善,自测阶段多次出现输出格式错误、无效元件未过滤的问题。
类图展示

3e87e602e5129cba4646dca2c5cabbc5
第三次作业:数字电路模拟程序3(子电路封装 + 全局异常检测)
作业要求
本次作业为单元最终迭代版本,在前两代组合逻辑电路基础上,新增两大核心高阶功能:子电路模块化封装复用与全局电路拓扑异常检测。支持自定义子电路定义、内部元件互连、多层模块嵌套、顶层调用子电路引脚;同时全面校验电路拓扑合法性,拦截所有非法连接、信号冲突、输出短接等违规场景,打印标准化错误信息并终止程序,完全对标工业级仿真软件的容错机制。
设计思路
本次作业对代码架构进行全面分层重构,彻底摒弃前两代的耦合式设计,严格按照单一职责原则拆分九大独立模块,实现极致解耦:
1 底层数据层:Signal 信号类、Pin 引脚类,纯数据载体,负责存储、读写、校验电平信号;
2 核心实体层:Component 顶层抽象组件类、Gate 逻辑门子类、SubCircuit 子电路类;
SubCircuit 为本次核心新增类,独立封装子电路名称、专属输入输出引脚集合、内部元件列表、内部互连语句,实现子电路独立仿真运算、模块复用;
3 工具服务层:ExceptionChecker 异常校验类、DriveResolver 信号驱动解析类、CircuitBuilder 电路构建类、Simulator 仿真调度类、OutputPrinter 输出打印类;
每个工具类职责绝对单一,仅负责一项业务,彻底消除巨型 Main 上帝类;
4 异常校验体系:独立实现拓扑规则校验,拦截四大非法场景:多输出短接、输入输出顺序颠倒、无有效输出、单输入多驱动冲突。
本次设计的核心亮点是模块化与防御性编程,通过子电路类实现电路模块复用,解决了重复电路冗余编码问题;通过全局异常检测,解决了非法输入导致的空指针、逻辑错乱、拓扑违规问题,代码鲁棒性实现质的提升。同时分层架构让代码拓展性拉满,后续新增时序元件、子电路嵌套、复杂拓扑规则,无需改动核心框架。
复杂度分析(SourceMonitor)

屏幕截图 2026-06-24 194546

屏幕截图 2026-06-24 194536

本次作业代码总行数 728 行,有效代码 685 行,架构分层清晰,高复杂度集中在核心业务工具类,无整体臃肿问题:
1 ExceptionChecker 校验方法 v (G)=7、ev (G)=3,覆盖四类异常校验逻辑,通过卫语句拆分分支,无嵌套冗余;
2 SubCircuit.eval () 子电路仿真方法 v (G)=6,需要完成内部信号分发、元件运算、输出引脚同步,流程复杂但结构清晰;
3 CircuitBuilder 构建方法 iv (G)=8,依赖多个全局容器,耦合度相对较高,但属于正常业务依赖;
4 全项目平均 OCavg=2.4,所有类均符合单一职责规范,无高风险病态代码。
解读与心得
本次迭代是我本单元收获最大的一次开发,彻底理解了分层架构与模块化设计的工程意义。前两代代码耦合度高、复用性差、无容错能力,仅能实现基础功能;第四代通过分层拆分、模块封装、异常拦截,让代码从 “作业代码” 升级为 “工程级代码”。
同时我也意识到,优秀的面向对象设计不仅仅是继承多态的简单使用,更是职责拆分、解耦复用、容错兜底、规范统一的综合体现。子电路类的组合复用、工具类的无状态服务、异常体系的全局兜底,都是工业软件开发的核心规范,也为我后续学习复杂项目开发打下了坚实基础。
类图展示

63AB90020529C3045759ABE646B75EBB

三、采坑心得
本单元三次迭代作业的踩坑点全部集中在硬件规则理解偏差、边界条件缺失、代码耦合冗余、异常校验不全、文本解析失误、输出格式不规范六大维度,所有问题均有具体测试数据、报错场景、修复方案支撑,绝非空泛总结。
坑点 1:初代电路引脚信号迭代收敛不彻底(作业 1)
问题现象:强测 3 个测试点 WA,部分多级互连电路电平更新滞后,最终输出电平错误。
数据支撑:自测多级串联门电路时,第一轮迭代仅更新一级信号,后续引脚信号未同步刷新,电路未完全收敛就执行运算。
错误根源:初代信号推送逻辑仅单次遍历更新,未实现循环迭代至全局稳定,多级拓扑电路信号传递不彻底,存在滞后性。
解决方案:重构信号推送逻辑,采用循环遍历机制,持续更新所有引脚信号,直至连续两次迭代电平无变化,判定电路收敛后再执行所有元件运算。
反思:数字电路是动态实时系统,信号传递是逐级迭代的,不能静态单次计算,必须模拟硬件实时电平刷新机制,这是电路仿真的核心逻辑。
坑点 2:复合元件引脚分段编号识别错误(作业 2)
问题现象:三态门、译码器运算结果全部失效,样例 7、样例 8 完全 WA,无正确输出。
数据支撑:自测三态门控制引脚读取错误,误读取输入引脚电平,导致高阻判断颠倒;译码器错误读取输入引脚作为控制引脚,使能条件永远不满足,全部输出被过滤。
错误根源:未严格遵循题目控制 - 输入 - 输出分段引脚规则,沿用基础门引脚读取逻辑,硬编码引脚编号错误,混淆控制引脚与数据引脚。
解决方案:为每一类复合元件单独定义固定引脚映射,三态门固定 0 号控制、1 号输入、2 号输出;译码器固定 0-2 为控制引脚、3 起为输入引脚,严格匹配题目硬件规范。
反思:硬件仿真程序规则大于逻辑,所有引脚编号、使能条件、输出格式都是硬性标准,不能主观臆断、复用旧逻辑,必须逐类适配硬件规则。
坑点 3:多格式输出分支混乱、格式不匹配(作业 2)
问题现象:译码器、数据分配器输出格式与样例不符,出现多余引脚编号、无效字符,全部 WF。
数据支撑:自测样例 8 译码器输出M(2)1-6:0,标准答案为M(2)1:0;样例 10 分配器无-无效占位符,格式完全错误。
错误根源:输出模块未区分九类元件输出规则,统一使用基础门输出模板,未单独处理译码器无引脚输出、分配器多字符拼接逻辑。
解决方案:重构输出打印模块,通过元件类型编码分层判断,单独编写译码器、分配器、三态门、基础门四类输出逻辑,严格匹配题目差异化格式。
反思:迭代开发中,新增功能必须配套新增输出逻辑,不能复用旧模板,分支预判要全面,避免格式适配遗漏。
坑点 4:拓扑非法场景无校验,违规输入触发异常(作业 3)
问题现象:输入包含输出短接、单输入多驱动、连接顺序颠倒的非法拓扑时,程序直接空指针崩溃,无错误提示。
数据支撑:自定义非法测试用例 5 组,全部触发程序闪退,无法拦截违规电路拓扑。
错误根源:前三代代码无任何异常校验机制,默认输入全部合法,不具备防御性编程能力。
解决方案:独立编写 ExceptionChecker 工具类,逐行校验连接语句合法性,拦截四类拓扑错误,打印标准化 ERROR 信息并终止程序。
反思:工程级代码必须具备容错兜底能力,永远不要信任外部输入,防御性编程是代码鲁棒性的核心保障。
坑点 5:子电路内部信号同步失效(作业 3)
问题现象:子电路内部元件运算正常,但对外输出引脚无信号,顶层无法读取子电路数据。
数据支撑:自测嵌套子电路用例 3 组,子电路内部运算正确,但顶层输出为空,功能失效。
错误根源:子电路 eval 方法仅完成内部信号分发与元件运算,未将内部元件输出电平同步至子电路对外输出引脚,数据流转断裂。
解决方案:新增子电路输出同步逻辑,运算结束后遍历内部元件,将指定元件输出信号写入子电路对外输出引脚,完成数据闭环。
反思:模块化封装必须保证内部 - 外部数据闭环,模块隔离不能造成数据断层,数据流完整性是模块复用的核心前提。

四、改进建议
结合三次迭代作业的开发复盘、代码复杂度分析、自测 Bug 汇总,针对现有代码架构、逻辑、鲁棒性、可拓展性,提出五点可落地、可持续迭代的优化方案,适配后续时序电路、子电路嵌套、异常检测全功能迭代需求。
1. 消除魔法数字,统一常量管理
当前代码中大量硬件规则参数(引脚编号、控制条件、元件排序序号、输出占位符、译码器使能条件)均为硬编码魔法数字,散落于各个子类与工具类,修改维护极其繁琐。后续可新建Constants 全局常量工具类,将所有固定硬件参数、规则阈值、格式符号统一封装为静态常量,所有业务逻辑直接引用常量。修改硬件规则时仅需改动单一常量类,大幅提升代码可维护性,杜绝参数修改遗漏问题。
2. 抽取通用引脚工具类,消除代码冗余
九类元件的引脚信号读取、有效性校验、编号解析存在大量重复代码,每个子类都重复编写引脚获取、判空、电平转换逻辑。后续可新建PinUtil 工具类,封装getPinSignal()、isPinValid()、parsePinIndex()等通用静态方法,所有元件统一调用工具类完成引脚操作,彻底消除冗余重复代码,统一引脚校验规则,降低代码圈复杂度。
3. 引入工厂模式优化元件创建逻辑
当前元件创建逻辑存在大量 if-else 分支,九类元件逐一判断,代码冗长、拓展性差。后续引入简单工厂模式,新建 GateFactory 工厂类,根据元件标识符统一创建对应元件实例,彻底消灭长分支判断。新增元件时仅需拓展工厂类匹配规则,无需修改核心业务代码,完美落地开闭原则。
4. 搭建自动化单元测试体系
目前所有测试均依赖手动输入样例、人工比对输出,测试效率低、边界覆盖不全。后续基于 JUnit 搭建自动化测试体系:
为每一类电路元件编写独立单元测试,单独校验运算逻辑正确性;
内置所有官方样例,自动运行、比对输出、标记错误用例;
批量生成边界用例:引脚缺失、控制无效、拓扑非法、子电路嵌套极端场景,实现全覆盖自动化测试,大幅提升迭代效率。
5. 预适配时序电路迭代需求
本次四代代码均为组合逻辑电路,无时序状态存储、无反馈环路,无法适配第三代时序电路作业需求。后续优化抽象父类结构,新增reset()状态重置方法、updateState()时序更新方法,组合电路空实现,预留时序元件拓展接口;同时新增环路检测机制,避免反馈电路无限迭代死锁,提前适配后续时序电路迭代开发。
五、总结
1. 本单元学到的知识与能力
理论知识层面
系统掌握了 Java 面向对象封装、继承、多态、抽象四大核心特性,熟练运用抽象类定义统一规范、子类实现差异化逻辑;深度理解单一职责、开闭原则、分层解耦等软件工程设计思想;掌握数字电路九类核心器件的硬件运算规则、引脚分段机制、拓扑信号流转原理;学会使用 SourceMonitor 量化分析代码质量、通过类图梳理程序架构。
工程实践层面
熟练掌握复杂多行文本解析、拓扑信号迭代收敛、模块化封装、异常容错处理等核心工程能力;彻底摆脱面向过程堆砌代码的思维,建立分层设计、模块解耦、防御编程、规范迭代的工程思维;能够独立完成小型仿真软件的迭代开发、架构重构、Bug 复盘、优化升级,具备基础的项目迭代开发能力。
2. 自身存在的不足
一是设计模式运用薄弱,代码架构仍依赖基础继承封装,未熟练运用工厂、组合等设计模式优化代码结构,部分模块分支冗余;
二是前置架构规划能力不足,初代代码耦合度高,后期迭代需要大规模重构,未做到一次规划、长期迭代;
三是自动化测试能力缺失,过度依赖人工测试,边界场景覆盖不全,自测效率低;
四是复杂规则整合能力不足,面对多类型、多分支、多格式的复杂业务规则,初期编码容易出现逻辑遗漏、格式错乱问题。
3. 后续学习规划

后续将重点学习常用设计模式,针对性优化代码架构;系统学习 JUnit 单元测试,养成开发即测试的工程习惯;深耕面向对象架构设计思维,提升前置建模、分层规划能力,避免迭代重构;同时预习时序电路、子电路嵌套、复杂异常检测等高阶知识点,为后续课程开发打下坚实基础。

本单元的三次迭代开发,让我真正明白:面向对象编程的核心不是语法,而是抽象与架构。优秀的代码不仅要实现功能,更要结构清晰、低耦合高内聚、可迭代可维护、具备容错能力。从简单功能实现到工程级规范开发,从堆砌代码到架构设计,本单元的成长将为我后续所有编程学习、项目开发提供至关重要的指导意义。

posted @ 2026-06-24 20:54  何俊豪  阅读(3)  评论(0)    收藏  举报