数字电路模拟程序

一、前言

本次数字电路模拟系列作业共分为三个迭代版本,以数字逻辑电路的计算机仿真为核心场景,遵循面向对象设计的核心原则,采用逐步迭代的开发方式,从最基础的五种逻辑门电路出发,逐步扩展组合逻辑元件、子电路复用与异常检测体系,最终形成一套功能完整、鲁棒性强、扩展性良好的电路仿真程序。三次作业在功能上层层递进,在设计上持续优化,完整覆盖了面向对象基础、继承多态、组合聚合、设计模式应用、鲁棒性设计等多个核心知识点,是对面向对象编程能力的系统性训练。

第四次作业(数字电路模拟程序 - 1)

题目大纲:实现基础数字电路模拟程序,支持与门、或门、非门、异或门、同或门五种基础逻辑元件。程序能够解析标准格式的电路连接指令,自动维护信号连接关系,通过迭代式电平传播算法计算所有元件的输出电平,最终按照 “与门→或门→非门→异或门→同或门” 的固定类型顺序,输出所有具备有效输入的元件的输出引脚电平,无有效输入的元件自动忽略不输出。
知识点:

基础类划分:程序按照单一职责原则拆分为抽象基类、具体元件类、信号实体类、核心处理器类与主程序入口类共 9 个类,每个类仅负责自身领域内的逻辑,避免单类职责膨胀。其中Men作为所有门电路的抽象父类,封装通用属性与方法;五个具体门类分别实现自身的逻辑运算;Signal封装引脚与电平的对应关系;CircuitHandler承担输入解析、信号调度、计算控制、结果输出的全流程调度;Main仅作为程序入口,不包含任何业务逻辑。

继承与多态应用:通过抽象基类定义统一的计算接口与属性规范,所有具体门电路都继承自该基类并重写计算方法。核心调度时仅面向抽象基类编程,无需感知具体元件类型,利用多态特性实现统一调度,新增元件时无需修改原有调度逻辑,初步体现开闭原则。

迭代信号传播算法:针对多级串联电路的依赖问题,采用循环迭代的计算方式,每一轮遍历所有元件更新输出并同步信号,直到本轮无任何信号变化时终止,确保所有可计算的元件都能得到稳定正确的输出结果。

输出规则实现:严格遵循题目指定的输出顺序与格式要求,对元件进行多级排序,同时过滤无效输出元件,保证输出结果的规范性与正确性。

题量:源码约 277 行,共 9 个类。输入输出逻辑清晰,仅需处理连接指令解析与计算结果格式化输出。
难度:中等。核心难点在于理解继承多态在业务场景中的落地方式,掌握迭代传播算法解决多级电路的依赖计算问题,同时准确实现五种逻辑门的运算规则。

第五次作业(数字电路模拟程序 - 2)

题目大纲:在第四次作业的基础上进行功能扩展,新增三态门、译码器、数据选择器、数据分配器四类组合逻辑元件,元件总数达到 9 种。新增元件普遍包含控制引脚与多输出引脚,需要区分有效输出与无效输出状态,实现控制端到通道的二进制编码映射逻辑,同时完全兼容原有五种基础门的所有功能、连接规则与输出格式,保证版本迭代的向后兼容性。
知识点:

继承体系扩展:在原有Men继承链上新增四个元件子类,完全复用基类的引脚管理、信号读写、状态标记等通用逻辑,仅扩展自身的引脚定义与计算规则,严格遵循开闭原则,在不修改核心调度代码的前提下完成功能扩展。

引脚分类设计:将元件引脚划分为控制引脚、输入引脚、输出引脚三类,不同引脚遵循不同的连接规则与计算逻辑。控制引脚用于决定元件工作状态与通道选择,输入引脚用于接收待运算信号,输出引脚用于输出运算结果,三类引脚编号独立划分,职责清晰。

无效状态统一机制:引入-1作为无效输出的统一标记值,三态门高阻态、译码器控制无效状态、数据分配器未选中通道均标记为无效值。输出时自动过滤完全无效的元件,信号同步时自动移除无效引脚的信号,保证整个系统状态的一致性。

二进制编码映射逻辑:译码器、数据选择器、数据分配器三类元件均涉及控制端二进制编码到通道编号的映射,需要准确处理引脚编号与位权的对应关系,实现 n 位控制端对应 2ⁿ个通道的通用换算逻辑。

题量:源码约 542 行,共 13 个类。输入输出复杂度显著提升,需要区分 9 种元件的输出格式,处理多引脚连接、无效状态过滤、编码计算等多种场景。
难度:偏难。核心难点在于准确理解各类元件的引脚规范与运算逻辑,正确实现二进制编码的高低位对应关系,同时设计统一的无效状态管理机制,保证多输出元件的信号同步准确无误。

第六次作业(数字电路模拟程序 - 4)

题目大纲:在前两次电路模拟的基础上,新增子电路定义与引用功能,支持将基础电路封装为可复用的功能模块,在主电路中可以像普通元件一样引用子电路,实现电路的模块化构建与复用;同时新增完整的异常输入检测机制,按照固定优先级处理五类连接异常,保证程序对非法输入的容错能力。设计上引入组合模式思想,将子电路与基础元件统一抽象为电路组件,支持层级化的电路构建。
知识点:

组合设计模式应用:将基础逻辑门视为组合模式中的叶子节点,将子电路视为组合节点,二者对外具备一致的端口交互特性。子电路内部封装独立的元件集合与连接关系,对外仅暴露输入输出端口,隐藏内部实现细节,既实现了电路复用,又保证了封装性。

子电路命名隔离机制:为每个子电路分配独立的编号,子电路内部的所有元件自动添加编号前缀,与主电路及其他子电路的命名空间完全隔离,避免不同子电路间元件编号相同导致的冲突。子电路仅通过端口与外部交互,内部元件对外部不可见。

分级异常检测体系:按照题目指定的优先级,依次检测 “包含多个输入源”“无输入源”“无接收端”“输入输出顺序错误”“输入信号冲突” 五类异常,仅输出首个出现的最高优先级异常,保证错误提示的唯一性与规范性。异常检测在连接解析阶段前置执行,发现错误后终止后续处理,避免非法数据进入计算流程。

全局导线连接模型:引入wireMap维护所有导线的连接关系,driverMap记录每个接收引脚的驱动源,构建全局的信号连接网络。每次迭代计算时,先同步所有导线上的信号,再计算元件输出,解决跨子电路端口、多级嵌套电路的信号自动传递问题,确保信号在整个电路网络中正确传播。

题量:源码约 500 行,共 13 个类。输入输出逻辑最为复杂,需要处理子电路定义、主电路引用、异常拦截、层级化输出等多类场景,边界条件多,状态管理复杂。
 
难度:较难,为三次作业中难度最高的版本。需要同时兼顾组合模式的设计落地、子电路命名空间的隔离、异常优先级的准确判定、多级信号的正确传播,涉及的场景与边界条件远超前两个版本,对程序设计的整体性与细节把控能力要求更高。

二、设计与分析

本次三次作业全程遵循面向对象设计的核心原则,以 “高内聚、低耦合” 为设计目标,在迭代过程中持续优化类结构与交互逻辑。以下结合每个版本的类结构设计、类间关系、核心算法实现进行详细分析。

第四次作业

本次作业是整个系列的基础版本,核心目标是搭建可扩展的类继承体系,实现基础的电路仿真功能。整体设计围绕 “职责拆分” 与 “继承复用” 两个核心展开。
在类结构设计上,Men抽象基类承担了所有门电路的共性封装:它包含元件名称、类型、编号等基础属性,包含引脚源数组用于记录每个输入引脚的信号来源,包含输出值属性存储计算结果。同时,它定义了compute抽象方法作为所有元件的统一计算接口,还提供了设置引脚源、获取输出值等通用方法。这种设计将所有元件的共性完全抽取到父类中,子类仅需关注自身的差异化逻辑,大幅减少了重复代码。
五个具体门类AONXY都继承自Men基类,仅重写compute方法实现各自的逻辑运算。其中与门遍历所有输入,存在 0 则输出 0;或门遍历所有输入,存在 1 则输出 1;非门对单输入取反;异或门在两输入不同时输出 1;同或门在两输入相同时输出 1。每个类的代码都非常精简,职责单一,仅负责自身的运算规则,符合单一职责原则。
CircuitHandler作为核心处理器,是整个程序的调度中心。它内部维护信号列表与元件列表,提供信号读写的基础方法,同时承担输入解析、连接绑定、迭代计算、排序输出四项核心职责。在连接解析时,程序会自动根据引脚名称创建对应的元件实例,自动绑定输入引脚的信号源;在迭代计算时,采用 “信号变化驱动” 的循环策略,每一轮遍历所有元件,对输入完备的元件执行计算并更新输出信号,直到整轮遍历没有任何信号变化为止,确保计算结果收敛。

源码分析:

屏幕截图 2026-06-24 152239

 

屏幕截图 2026-06-24 152258

 

 

类图:

image

 

 

类间关系详解

1.泛化(继承)关系:Men抽象基类与AONXY五个具体门类是典型的泛化关系。子类继承父类的所有非私有属性与方法,并重写父类的抽象方法compute,符合里氏替换原则,所有出现父类的地方都可以用子类替换,这也是核心调度逻辑可以统一面向Men编程的基础。

2.聚合关系:CircuitHandlerMenCircuitHandlerSignal均为聚合关系。CircuitHandler作为整体,持有List<Men>门元件集合与List<Signal>信号集合,但门元件与信号都可以独立于处理器存在,二者的生命周期没有强绑定,处理器只是对元件与信号进行统一管理,属于 “弱拥有” 的聚合关系。

3.依赖关系:Main类与CircuitHandler是依赖关系,Main仅在main方法中临时创建CircuitHandler实例并调用其方法,属于 “使用” 关系,没有长期持有成员引用;同时Men类的计算逻辑依赖CircuitHandler提供的信号读写能力,计算过程中需要通过处理器获取输入信号的值,属于方法级别的依赖关系。

4.关联关系:Men内部通过引脚源数组与信号形成间接关联,每个输入引脚都记录了对应的信号源名称,通过处理器可以查找到对应的信号值,是结构化的引用关联。

在类间关系上,Men与五个子类是典型的泛化(继承)关系;CircuitHandlerMenSignal是聚合关系,处理器聚合管理所有元件与信号实例;MainCircuitHandler是依赖关系,主程序仅依赖处理器启动整个流程。整体结构层次清晰,耦合度低,为后续版本的功能扩展打下了良好的架构基础。
心得:通过抽象基类统一接口,让核心调度逻辑完全面向抽象编程,而非面向具体实现编程。这种设计让后续新增元件时,核心调度代码完全不需要修改,仅需新增子类即可,充分体现了开闭原则 “对扩展开放,对修改关闭” 的核心思想

第五次作业

本次作业在 V1 的架构基础上进行功能扩展,核心目标是在不破坏原有架构的前提下,新增四类组合逻辑元件,同时适配多输出、无效状态等新特性。
为了适配多输出元件的需求,首先对Men基类进行了升级:将原本单值的输出属性替换为Map<Integer, Integer>结构的输出映射表,支持存储多个引脚的输出值;同时新增setOutputInvalid方法,统一将指定引脚标记为-1无效值。这种升级完全向后兼容,原有单输出元件依然只使用 0 号引脚,不会受到任何影响,保证了版本迭代的兼容性。
在新增元件的设计上,每个元件都严格遵循自身的数字逻辑规范:

三态门S设置 0 号引脚为控制端、1 号引脚为输入端、2 号引脚为输出端。当控制端为高电平时,输出跟随输入;当控制端为低电平时,输出标记为无效高阻态,符合三态门的总线特性。

译码器M设置前 3 个引脚为控制端,后续为输入引脚,最后为输出引脚。只有当控制端满足 “1、0、0” 的使能条件时,才根据输入二进制编码将对应输出引脚置 0、其余置 1;控制无效时所有输出引脚标记为无效。

数据选择器Z前半段为控制引脚,中间为多路输入引脚,最后为单输出引脚。根据控制端的二进制编码,从多路输入中选择对应通道的信号输出,实现多路选通的功能。

数据分配器F前半段为控制引脚,中间为单路输入引脚,最后为多路输出引脚。根据控制端编码将输入信号送到对应输出通道,其余未选中通道全部标记为无效。

在核心计算逻辑上,CircuitHandler的迭代算法进行了适配优化:每次元件计算完成后,遍历其所有输出引脚,有效信号更新到信号列表,无效信号主动从信号列表中移除。这种机制保证了信号状态的准确性,避免无效信号残留导致下游元件误计算。同时,元件创建逻辑仅新增了四个分支,迭代计算的核心循环完全不变,体现了架构的可扩展性。

源码分析:

屏幕截图 2026-06-24 160648

 

屏幕截图 2026-06-24 160702

 

 

类图:

d71d1416ee0fad370c08ef570178dcef

 

在核心计算逻辑上,CircuitHandler的迭代算法进行了适配优化:每次元件计算完成后,遍历其所有输出引脚,有效信号更新到信号列表,无效信号主动从信号列表中移除。这种机制保证了信号状态的准确性,避免无效信号残留导致下游元件误计算。同时,元件创建逻辑仅新增了四个分支,迭代计算的核心循环完全不变,体现了架构的可扩展性。
在输出逻辑上,针对不同类型的元件设计了差异化的输出格式:基础门与三态门、选择器输出 “元件名 - 引脚号:电平” 格式;译码器仅输出低电平引脚的编号;数据分配器按顺序输出所有引脚状态,无效位用-填充。输出前先按类型优先级、再按元件编号排序,严格匹配题目输出规范。

类间关系详解

1.泛化(继承)关系:新增的SMZF四个类均继承自Men抽象基类,与原有五个子类平级,共同构成完整的元件继承树。所有子类都可以替换父类在调度逻辑中使用,进一步验证了继承体系的扩展性,开闭原则得到了充分体现。

2.组合关系:Men基类内部的输出映射表outputValues、引脚源数组与元件对象之间是组合关系。这些属性是元件对象的固有组成部分,与元件对象同生共死,元件实例创建时属性随之初始化,元件销毁时属性也随之消失,属于 “强拥有” 的组合关系。

3.聚合关系:CircuitHandler与所有门类依然保持聚合关系。虽然元件种类增加,但处理器只是统一管理所有元件实例,元件的生命周期不与处理器绑定,依然是弱拥有的聚合关系。

4.依赖关系:CircuitHandler的计算逻辑依赖每个元件的compute方法,输出逻辑依赖不同元件的类型判断,均属于依赖关系。处理器通过调用元件的方法完成计算与输出,不需要感知元件内部的具体实现。

心得:通过基类的兼容升级,实现了 “单输出元件” 到 “多输出元件” 的平滑扩展,同时通过统一的无效值标记,让不同类型的元件状态可以用同一套机制管理。这种设计既满足了新功能的需求,又最大程度复用了原有代码,控制了版本迭代的代码改动量。

第六次作业

本次作业是功能最完整、架构最完善的版本,在 V2 的基础上引入了子电路复用与异常检测两大核心模块,同时引入组合模式思想重构了组件模型,让程序的模块化能力与鲁棒性得到质的提升。
 
为了实现子电路功能,新增了SubCircuit类用于描述子电路实体,它包含子电路编号、输入端口集合、输出端口集合三个核心属性,负责定义子电路的对外接口。子电路内部的元件通过命名前缀机制实现隔离:所有内部元件的全局名称都会自动加上C编号-前缀,确保不同子电路间即使元件编号相同,也不会产生命名冲突。这种命名空间隔离的实现方式简单高效,完美解决了模块化复用的命名冲突问题。
 
在信号传递机制上,摒弃了 V1、V2 版本仅在解析时传递一次信号的方式,改用全局导线连接模型。wireMap以源引脚为键、目标引脚列表为值,记录所有导线的连接关系;driverMap记录每个接收引脚的唯一驱动源,用于冲突检测。每次迭代计算时,先遍历所有导线,将源引脚的信号同步到所有目标引脚,再进行元件计算。这种模型完美解决了跨子电路端口的信号传递问题:子电路输入端口接收外部信号后,通过导线传递给内部元件;内部元件的输出通过导线传递给子电路输出端口,再传递到外部主电路,整个过程自动完成,无需特殊处理。
 
异常检测体系是本次作业的重点设计内容。按照题目指定的优先级顺序,将五类异常的检测逻辑嵌入连接解析流程:首先统计连接中的信号源数量与接收端数量,判断多输入源、无输入源、无接收端三类异常;接着检查顺序是否符合 “源在前、接收端在后” 的规则;最后检查每个接收引脚是否已经被其他源驱动,判断信号冲突。一旦检测到高优先级异常,立即记录错误信息并终止后续处理,保证仅输出第一个最高优先级的异常。这种前置检测的设计,将非法数据拦截在计算流程之外,避免了非法数据导致的程序崩溃,大幅提升了程序的鲁棒性。
 
在输出排序逻辑上,针对子电路场景进行了优化:所有子电路元件整体排在主电路元件之前;子电路之间按编号升序排列;同一电路内的元件按 “与门→或门→非门→异或门→同或门” 的类型优先级排序;同类型元件按编号升序排列。多级排序规则确保输出顺序完全符合题目要求。

源码分析:

屏幕截图 2026-06-24 162358

 

屏幕截图 2026-06-24 162408

 

 

 

类图:

8e5c96c2764396a3a2a0a866e4b394cb_720

 

 

类间关系详解

本次作业引入组合模式后,类间关系形成了清晰的层级结构,完全对应组合模式的标准类图:

1.泛化(继承)关系:重构后的Gate抽象基类与所有基础门类(AndGateOrGateNotGateXorGateXnorGate)是泛化关系,基础门对应组合模式中的Leaf 叶子节点,没有子节点,自身完成计算逻辑。

2.组合关系:SubCircuit(组合节点)与Gate之间是组合关系。子电路作为整体包含内部的所有门元件,元件的生命周期与子电路强绑定:子电路定义时创建内部元件,子电路销毁时内部元件也随之失效,属于 “强拥有” 的组合关系,完全符合组合模式中 Composite 与 Component 的包含关系。

3.聚合关系:CircuitHandlerSubCircuitCircuitHandlerGate均为聚合关系。处理器作为全局管理者,统一持有所有子电路实例与所有门元件实例,但子电路可以独立定义、独立引用,元件也可以存在于不同的子电路上下文中,生命周期不与处理器绑定,属于弱拥有的聚合关系。

4.依赖关系:

  Main依赖CircuitHandler启动程序,是入口级依赖;

  导线信号同步逻辑依赖wireMapdriverMap两个数据结构,是方法级依赖;

  异常检测逻辑依赖引脚类型判断方法,是功能级依赖;

  输出排序逻辑依赖元件的类型与编号属性,是数据级依赖。

5.关联关系:SubCircuit通过输入输出端口与外部电路形成关联,端口是子电路与外部交互的唯一接口,内部元件不直接与外部关联,保证了封装性。

心得:组合模式的应用让电路具备了无限扩展的可能,通过 “叶子元件 + 组合子电路” 的结构,可以构建任意复杂度的层级电路;而全局导线模型的引入,让信号传播逻辑变得统一且通用,无论多少层级的电路,都可以通过同一套迭代机制完成信号计算。同时,分级异常检测的设计思路也体现了鲁棒性设计的核心原则:错误早发现、早处理,避免错误扩散到核心业务逻辑中。

三、踩坑心得

三次作业的开发过程并非一帆风顺,每个版本都遇到了不少典型问题,通过定位问题、分析原因、修复验证的完整流程,提升自己的代码检错能力,虽然可能还是有点不足,但是积累了重要的学习经验。

第四次作业踩坑

  1. 单次遍历计算导致后级元件无输出
    开发初期,计算逻辑仅对所有元件执行一次遍历计算,运行后发现多级串联的电路中,只有第一级门电路有输出,后面所有门都被判定为输入无效。经过排查发现,第一次遍历时后级门的输入信号还未被前级门计算出来,因此直接跳过了计算,后续也不会再重新计算。
    解决方案是改为循环迭代计算,每一轮遍历所有元件更新输出并同步信号,设置changed标记记录本轮是否有信号变化,当一轮遍历没有任何变化时终止循环。修改后所有可计算的元件都能得到正确结果,多级串联电路完全正常。
  2. 输出排序规则错误
    最初实现排序时,仅按照元件编号从小到大排序,运行测试用例后发现输出顺序与预期不符。仔细核对题目要求后发现,输出必须先按元件类型的固定优先级排序,同类型才按编号排序。
    解决方案是在比较器中先获取两个元件类型在AONXY字符串中的索引,先按索引排序,索引相同时再按编号排序。调整后输出顺序完全符合题目规范。

    image

     

第五次作业踩坑

image

 

  1. 控制端高低位顺序颠倒
    开发译码器、数据选择器、分配器三类元件时,默认认为引脚号越小位权越高,导致所有编码计算结果完全错误,大量测试用例不通过。通过手动计算样例的编码结果,对比程序输出反推,发现引脚 0 对应的是最低位 2⁰,引脚 1 对应 2¹,引脚号越低位权越低。
    解决方案是修改编码计算逻辑,循环中用controlCode |= (controls.get(i) << i)实现第 i 号引脚对应第 i 位,修正后所有编码结果完全正确。
  2. 无效状态残留信号问题
    最初实现无效状态时,仅标记了元件内部的输出值为 - 1,但没有从全局信号列表中移除对应引脚的信号。导致三态门从导通切换到高阻态后,下游元件依然能读取到之前的有效值,造成计算错误。
    解决方案是在每次计算后遍历所有输出引脚,遇到无效值时主动从信号列表中删除对应条目,保证全局信号状态与元件状态一致。修改后无效状态的传递完全正确,下游元件会正确判定为输入无效。
  3. 三态门引脚编号定义错误
    最初想当然地沿用基础门的引脚定义,将 0 号引脚作为输出,导致连接解析时引脚绑定完全错位。重新查阅题目引脚规范后,明确三态门 0 号是控制、1 号是输入、2 号是输出,调整三态类的引脚常量定义后,连接与计算全部正常。

第六次作业踩坑

image

 

  1. 子电路端口解析导致数字格式化异常
    运行子电路样例时,程序直接抛出NumberFormatException,报错无法将字符串 “A” 转为整数。排查调用栈发现,在绑定引脚源时,代码默认所有带-的引脚都是 “元件名 - 引脚号” 格式,直接拆分后解析数字,但子电路端口C1-A的后缀是字母,解析失败。
    解决方案是在解析引脚号前,先判断后缀字符串是否为纯数字,非纯数字则判定为子电路端口,跳过元件绑定,仅记录导线连接关系。修改后子电路端口解析正常,程序不再崩溃。
  2. 信号仅解析时传递导致子电路无输出
    开发初期,信号传递只在解析连接时执行一次,导致子电路内部元件计算出结果后,无法自动同步到子电路输出端口,主电路始终收不到子电路的输出信号,所有多子电路用例全部失败。
    解决方案是引入wireMap全局导线模型,在每次迭代计算时,先遍历所有导线同步信号,让信号可以沿着导线自动传播,跨端口、跨层级自动传递。修改后子电路的信号可以正确传递到主电路,多级嵌套电路计算完全正常。
  3. 异常优先级顺序错误
    最初实现异常检测时,将信号冲突的检测放在了顺序错误之前,导致部分同时存在两类错误的用例,输出的异常类型与预期不符。重新核对题目优先级规则后,严格按照 “多输入源> 无输入源 > 无接收端 > 顺序错误 > 信号冲突” 的顺序调整检测代码,先检测高优先级错误,发现后直接返回,不再检测后续低优先级错误。调整后所有异常用例的输出完全符合题目要求。
  4. 未定义节点误判为信号源
    最初判断引脚类型时,所有不带-的字符串都被当成了顶层输入信号源,导致很多未定义的非法节点被误判为有效源,异常检测失效。解决方案是新增topInputs集合,在解析 INPUT 行时记录所有合法的顶层输入名称,判断引脚类型时,只有集合内的名称才算有效信号源,其余均判定为非法。修正后异常检测的准确率大幅提升。

四、改进建议

结合三次作业的迭代开发过程,从代码结构、可维护性、可扩展性三个维度,提出以下具体改进建议,进一步提升程序的设计质量与工程化水平。

代码结构优化

  1. 引入简单工厂模式封装元件创建
    当前三个版本的元件创建逻辑都散落在CircuitHandler中,以长串if-else分支的形式存在,每次新增元件都需要修改处理器代码,违反开闭原则。可以引入简单工厂模式,设计GateFactory工厂类,将所有元件创建逻辑封装到工厂类中,对外仅暴露createGate方法。CircuitHandler仅通过工厂获取元件实例,完全不需要感知具体的创建逻辑。
    这种优化不仅可以消除处理器中的长分支判断,还可以将元件创建的职责独立出来,符合单一职责原则,后续新增元件时仅需修改工厂类,不影响核心调度逻辑。
  2. 输出逻辑独立为报告生成类
    当前所有版本的输出逻辑都内嵌在CircuitHandler中,不同元件的输出格式判断混杂在一起,代码可读性差,修改输出格式时容易误改其他逻辑。可以将输出逻辑抽离为独立的ReportGenerator类,专门负责元件排序、格式拼接、结果打印,提供统一的print方法接收元件列表。
    这种优化实现了业务计算与输出展示的完全解耦,后续如果需要修改输出格式、新增输出项,仅需修改报告生成类,不影响核心计算逻辑,同时也让CircuitHandler的职责更加聚焦。

可维护性优化

  1. 完善异常体系,使用自定义异常类
    当前 V3 版本的异常处理仅通过字符串记录错误信息,表达方式原始,扩展性差。可以设计自定义异常类体系,创建基类CircuitException,派生出MultipleInputExceptionNoInputExceptionSequenceErrorExceptionSignalConflictException等具体异常子类,每个异常类封装自身的错误信息与优先级。
    在连接解析时检测到错误直接抛出对应异常,在Main方法中统一捕获处理。这种方式比字符串记录更规范,类型安全,扩展新异常类型时也更清晰,同时可以附带更多异常上下文信息,便于调试排查。
  2. 提取常量与枚举,消除魔法值
    当前代码中存在大量硬编码的魔法值,比如元件类型顺序字符串、引脚编号常量、异常提示文本等,散落在代码各处,修改时容易遗漏。可以提取专门的常量类,或者使用枚举类型进行管理,比如定义GateTypeEnum枚举管理所有元件类型与优先级,定义PinConstants接口管理引脚编号常量,定义ErrorMsgConstants管理异常提示文本。
    常量统一管理后,修改配置时仅需修改一处,避免多处修改导致的不一致问题,同时代码可读性也会显著提升。

可扩展性优化

  1. 完善组合模式,统一组件接口
    当前子电路与基础门只是隐式的组合关系,没有统一的抽象接口,子电路还不能像普通元件一样被直接调度,嵌套层级受限。可以定义统一的CircuitComponent抽象组件接口,规定getInputPortsgetOutputPortscompute等通用方法,基础门与子电路都实现该接口。
    完善后,子电路与基础元件具备完全一致的对外接口,可以任意层级嵌套,子电路内部还可以再引用其他子电路,真正实现无限层级的模块化电路构建,程序的扩展性会得到质的提升。
  2. 扩展时序电路仿真能力
    当前程序仅支持组合逻辑电路的仿真,没有状态记忆能力。后续可以学习时序电路的建模方法,新增 D 触发器、JK 触发器等时序元件,引入时钟信号驱动,加入状态更新机制,实现同步时序电路的仿真。在此基础上还可以扩展寄存器、计数器等常用时序模块,让程序的仿真能力覆盖更完整的数字电路场景。

五、总结

学习收获

通过本次三次数字电路模拟作业的迭代开发,我在面向对象设计、业务建模、工程化能力等多个维度都得到了显著提升,主要收获可以归纳为以下四点:
 
第一,深化了对面向对象核心原则与类间关系的理解。通过三个版本的迭代,我切实体会到了单一职责原则、开闭原则、里氏替换原则在实际开发中的指导意义,也彻底理清了泛化、聚合、组合、依赖四类核心关系的区别与适用场景。从最初的单类堆砌,到后来的继承体系,再到组合模式的应用,逐步学会了如何将复杂业务拆分为职责单一的类,如何通过继承、组合两种方式扩展功能而不破坏原有代码,如何设计高内聚低耦合的类结构。
 
第二,提升了业务场景的建模能力。数字电路是一个非常典型的结构化业务场景,从元件、引脚、信号,到连接、计算、输出,整个体系层次清晰。通过三次开发,我学会了如何将真实的业务规则转化为面向对象模型,如何用类与对象描述实体与关系,如何用方法与流程描述业务逻辑,完成了从需求到代码的完整转化过程。
 
第三,增强了程序的鲁棒性设计意识。从 V1 完全不考虑非法输入,到 V3 实现完整的分级异常检测,我逐渐理解了鲁棒性对程序的重要性。一个合格的程序不仅要在正常输入下正确运行,还要能处理各种非法输入,给出清晰的错误提示,而不是直接崩溃。通过前置校验、异常拦截、状态标记等手段,可以有效提升程序的容错能力与稳定性。
 
第四,掌握了迭代式开发的方法。三次作业是典型的迭代开发过程,每个版本都在前一版的基础上扩展功能。这个过程中我学会了如何设计可扩展的架构,如何保证版本间的向后兼容,如何在不破坏原有功能的前提下新增特性,这对后续的大型项目开发非常有价值。
posted @ 2026-06-24 18:03  曹译文  阅读(7)  评论(0)    收藏  举报