南昌航空大学-22207107-胡优乐-Java第二次Blog大作业

news/2025/2/26 18:08:59/文章来源:https://www.cnblogs.com/xixixixixi/p/18564483

前言

 在这段时间里,我们总共进行了三次大作业练习,基于这三次大作业的体量及设计的知识点,难度分布,我做了以下的总结:
1.第四次大作业总共有三道题,分别是:1.校园角色类设计-1;2.设计一个学生类和它的子类-本科生类;3.答题判断程序-4;实际做下来的体会是:
(1)第一题难度入门级别,涉及的知识点是:类与继承;多态的表现形式;构造方法等;
(2)第二题难度入门级别,涉及到的知识点是:类与继承;构造方法;方法重写;静态方法的使用;输入与字符串处理;多态的表现形式等;
(3)第三题难度为困难级别,涉及的知识点是:类与继承;集合的使用;正则表达式;接口与排序;字符串处理;异常处理;多态性的体现等;

  2.第五次大作业共有两道题:
第一题 家居强电电路模拟程序-1 难度级别:困难;涉及的知识点有:类的定义与抽象;继承关系与代码复用;接口与排序;多种集合类型的运用;正则表达式;条件判断与循环结构等;
第二题 阅读程序调试改正程序 难度级别:入门; 涉及的知识点有:类与对象;封装性的运用;集合的运用等;

3.第六次大作业共有一道题:
家居强电电路模拟程序-2 难度级别困难;涉及的知识点有:类的定义与抽象;继承关系与代码复用;接口与排序;多种集合类型的运用;正则表达式;条件判断与循环结构等;

设计与分析

1.答题判断程序-4
1.类的设计:

 1.1整体类结构和层次关系基础类与继承体系构建:代码构建了一个围绕考试相关业务的类层次结构,以Matter类作为基础类,它抽象地描述了题目相关的通用属性,如题目编号(qusid)、题干(qustent)、正确答案(correctAnswer)以及题目是否正确的标识(judgeRight)。

  在此基础上,通过继承关系派生出了ManySelectMatter(用于表示多选题)、TianKongMatter(用于表示填空题)等子类,这些子类复用了Matter类的属性和构造方法,同时又根据自身题型特点在这个继承体系中占据特定位置,体现了面向对象中通过继承实现代码复用和对不同类型题目进行分类抽象的设计思路。
关联类的协作:除了题目相关的类,还有诸如Examination类用于管理试卷中题目与分数的映射关系、Answer类用于表示学生的答案信息,包含了学生答题的具体内容以及对应的试卷和学生编号等;Pupil类则简单封装了学生的基本信息(学生编号和姓名)。
这些类相互协作,服务于整个考试数据处理的流程,例如Answer类会关联到Pupil类(表示是哪个学生的答案)、Examination类(对应哪张试卷的答案)以及通过题目编号间接关联到Matter类(答案对应的具体题目)。

1.2 各个类的职责与功能设计

Matter 类及其子类:

  Matter 类:作为基类,它的主要职责是封装题目共有的基本属性,并提供相应的访问方法(如returnQustent、returnQusid等)以及设置题目正确与否的方法(setIsRihgt),将题目相关的数据进行统一管理,对外提供获取和修改这些数据的接口,使得外部代码可以按照规范的方式与题目对象进行交互。

  ManySelectMatter 和 TianKongMatter 子类:这两个子类继承自Matter类,在功能上它们复用了父类的属性和构造方法初始化流程,但从业务角度来说,它们代表了不同的具体题型,各自没有额外添加独特的属性(只是复用了父类属性来满足自身题型需求),其存在更多是为了在整个系统中明确区分不同类型的题目,便于后续根据题型进行不同的处理逻辑,比如在判断答案正确性等环节可以针对不同题型执行不同规则。

  Examination 和 Exam 类:
Examination 类:重点关注试卷中题目与分数的对应关系,通过LinkedHashMap<Integer, Integer>来存储这种映射,提供了添加题目及对应分数的方法(addMatter)以及计算试卷总分的方法(calculateFullPoint),职责在于维护试卷的分值结构,方便后续基于分值进行各种统计和计算工作。

  Pupil 类:相对简单,主要就是对学生的基本身份信息(学生编号和姓名)进行封装,提供对应的获取方法(getPupilID和getName),作为整个系统中识别学生个体的基础类,为其他类(如Answer类关联学生)提供基本的学生信息来源。

  JudgeManychoice 类:这个类的功能比较单一且聚焦,主要用于处理多选题答案判断的逻辑,提供了choiceJudge方法,通过比较两个字符串数组(代表正确答案集合和学生作答答案集合)来判断答案的正确性,返回"true"(完全正确)、"partially correct"(部分正确)或"false"(错误)等结果,为在判断学生答案是否正确的环节中针对多选题的情况提供了专门的判断逻辑支持。

  ScannerParser 类:该类主要负责对输入的字符串按照特定格式进行解析,并根据不同的格式标识将解析后的数据存储到对应的集合对象中,起到了输入数据格式校验与初步处理的作用,是整个程序中对接外部输入数据的关键环节。

  WorkoutOutput 类:主要用于根据学生的答题情况、对应的试卷信息以及题目相关信息等,计算并输出学生的考试结果,是整个程序中对处理后的数据进行展示呈现的重要部分,将内部数据处理结果转化为直观的、可供用户查看的输出内容。

2.类图

2.家居强电电路模拟程序-1
1.类的设计

  1.1整体架构与类层次关系

  基础类与继承体系:代码以 HomeElectricalApparatus 类作为所有家用电器设备类的基类,它定义了通用的设备属性,即设备编号(apparatusId)和设备类型(apparatusType),这种设计体现了面向对象编程中对共性抽象的思想。
在此基础上,通过继承创建了多个子类,如 SpeedRegulatorApparatusType、SwitchApparatusType、ContinuouslyAdjustableApparatusType、IncandescentLightApparatusType、FluorescentLightApparatusType、FanApparatusType 等,每个子类代表一种具体类型的家用电器设备,它们继承了父类的属性,并根据自身设备的特点添加了特有的属性和行为,构建出了一个清晰的类层次结构,遵循了继承复用的原则,便于对不同类型设备进行统一管理和差异化处理。
类之间的协作关系:除了继承关系外,不同类之间还存在着紧密的协作关系。例如,CommandHandler 类用于处理输入的控制命令,它会操作存储在 LinkedHashMap<String, HomeElectricalApparatus> 中的具体设备对象(通过调用各子类的相应方法来实现具体功能,如开关切换、调速等操作);VoltageProcessor 类则负责模拟电压在这些设备间的传递以及根据电压来设置各设备的相关状态,同样依赖于存储设备对象的集合以及各设备子类自身的方法实现功能。而 ApparatusComparatorType 类为设备对象的排序提供了比较规则,使得在 Main 类中可以对处理后的设备列表按照特定顺序进行展示,这些类相互配合,共同实现了对家用电器设备的管理、控制以及状态展示等功能,形成了一个相对完整的功能体系。

  1.2各个类的详细分析

  1. HomeElectricalApparatus 类
    职责与功能:作为基类,它的主要作用是抽象出家用电设备的基本属性,提供了设备编号和设备类型这两个核心属性的定义以及对应的访问方式(通过构造函数初始化属性,并可以通过成员变量直接访问)。同时定义了 displayInfo 方法,虽然在基类中该方法默认返回空字符串,但它为子类重写提供了一个统一的接口,用于展示不同设备的特定信息,是整个类层次结构中实现多态展示设备信息的关键设计点。

  2. 各子类(SpeedRegulatorApparatusType、SwitchApparatusType 等)
    属性与行为扩展:
    SpeedRegulatorApparatusType 类:添加了 speedLevelValue 属性用于表示调速设备的速度级别,通过 generateOutputVoltage 方法根据速度级别返回相应的输出电压值,并重写了 displayInfo 方法来展示设备编号和当前速度级别,体现了针对调速设备特有的功能和信息展示需求进行的设计,实现了对调速设备在这个模拟系统中的具体行为建模。

  SwitchApparatusType 类:包含 isSwitchedOn 属性用于表示开关状态,提供了 toggleSwitch 方法来切换开关状态,其 generateOutputVoltage 方法根据开关状态决定是否输出输入电压,displayInfo 方法展示设备编号和开关状态对应的文字描述(“closed” 或 “turned on”),完整地刻画了开关设备在系统中的操作和状态呈现方式。

  ContinuouslyAdjustableApparatusType 类:引入 parameterValueAmount 属性来表示连续可调设备的参数值,有 setParameterValue 方法用于设置该参数,generateOutputVoltage 方法根据参数值与输入电压计算输出电压,displayInfo 方法展示设备编号和格式化后的参数值,满足了连续可调设备在参数设置及相关功能、信息展示方面的要求。

  IncandescentLightApparatusType 类:具备 brightnessLevelValue 属性记录白炽灯的亮度级别,通过 setBrightnessValue 方法根据输入电压按照不同的范围条件设置亮度值,displayInfo 方法展示设备编号和亮度级别,针对白炽灯根据电压改变亮度这一特性进行了合理的功能设计。

  FluorescentLightApparatusType 类:同样有 brightnessLevelValue 属性,其 setBrightnessValue 方法简单地根据输入电压是否为 0 来设置亮度(非 0 则设为固定值 180),displayInfo 方法展示相应信息,体现了荧光灯亮度设置相对简单的特点。

  FanApparatusType 类:包含 speedValue 属性表示风扇的转速,setRotationSpeedValue 方法依据输入电压在不同的范围条件下设置转速,displayInfo 方法展示设备编号和转速,实现了对风扇设备转速调节及信息展示的功能模拟。

  共性与差异体现:这些子类都继承自 HomeElectricalApparatus 类,复用了父类的设备编号和设备类型属性,同时各自按照设备的实际功能需求添加了独特的属性和对应的行为方法,重写了 displayInfo 方法以展示自身特有的关键信息,既体现了作为家用电器设备的共性(在整体系统中被统一管理、有通用的基础属性等),又突出了不同类型设备之间的功能差异。

  1. ApparatusComparatorType 类
    功能实现:该类实现了 java.util.Comparator 接口,通过重写 compare 方法定义了设备对象之间的比较规则。具体来说,先按照预设的设备类型顺序(通过 typeOrder 数组定义)对设备进行排序,如果设备类型相同,则进一步按照设备编号(截取编号字符串并转换为整数后比较)进行排序,以此实现了一种灵活且符合特定业务需求的设备对象排序机制,方便在需要展示设备列表时按照一定顺序输出,例如在 Main 类中对处理后的设备列表进行有序展示就依赖于此比较规则。

  2. CommandHandler 类
    命令处理逻辑:作为命令处理的核心类,它提供了静态方法 handleCommands,接收存储设备对象的映射表(LinkedHashMap<String, HomeElectricalApparatus>)和控制命令列表(LinkedList)作为参数。在方法内部,通过循环遍历控制命令列表,根据命令字符串的开头标识(如 #K、#F、#L 等)来判断命令类型,然后按照不同的命令格式解析并调用相应设备子类的方法执行具体操作,例如对于开关类设备的开关切换、调速设备的速度调节、连续可调设备的参数设置等操作,实现了将输入的控制命令转化为对具体设备对象操作的功能,是整个系统中实现用户交互控制设备的关键环节。

  3. VoltageProcessor 类
    电压处理流程:此类负责模拟电压在不同类型家用电器设备之间的传递以及对设备状态的影响,通过 processVoltage 方法实现相关功能。方法内部首先获取存储设备对象的列表(LinkedList),并设定初始输入电压值,然后通过两次遍历设备列表,第一次根据部分设备(开关类、调速类、连续可调类)对电压的影响来更新输入电压值,第二次根据剩余设备(白炽灯、荧光灯、风扇等)根据更新后的电压值来设置自身的状态(如亮度、转速等),完整地模拟了电压在整个电器系统中的作用过程以及各设备对电压的响应情况,是实现设备状态根据电压变化而动态调整的关键所在。

2.类图

3.家居强电电路模拟程序-2
1.类的设计
1.1整体类结构设计思路
基于题目描述的家居电路模拟需求,设计一套类结构来对各种电路设备、电路连接情况以及相应的控制与状态展示进行建模。整体思路是以抽象出的公共特征为基础构建基类,然后通过继承等方式派生出不同类型的具体类,同时考虑不同电路结构(串联、并联)也作为类来表示,使得各类之间相互协作,共同完成家居电路的模拟功能。
1.2具体类设计

  1. 电路设备基类(CircuitDevice)
    属性:
    deviceId:String类型,用于标识设备的编号,例如 K1、F3 等,遵循题目中设备标识的格式要求,通过它可以唯一区分不同的设备个体。
    deviceType:String类型,存储设备的类型标识符,如 K(开关)、F(分档调速器)、L(连续调速器)、B(白炽灯)、R(日光灯)、D(吊扇)、A(落地扇)等,方便根据类型进行不同的行为处理。
    方法:
    getDeviceId():返回设备编号,用于外部获取设备的唯一标识。
    getDeviceType():返回设备类型标识符,使得其他类可以知晓该设备所属类型,进而执行相应的逻辑。
    displayStatus():定义一个抽象方法,用于展示设备当前的状态或参数,不同的子类会根据自身设备特点重写该方法来返回具体的状态信息,符合多态性的设计原则,例如开关展示开关状态,调速器展示档位信息,灯展示亮度,风扇展示转速等。
  2. 控制设备类(ControlDevice)
    继承关系:继承自 CircuitDevice 类,复用基类的设备编号和设备类型属性,同时扩展控制设备特有的行为和属性。
    属性:
    inputPin:int 类型,代表输入引脚编号,对于所有控制设备(开关、调速器等),按照题目要求输入引脚编号固定为 1,但通过属性定义方便后续可能的扩展或灵活配置。
    outputPin:int 类型,代表输出引脚编号,固定为 2,同样考虑到可扩展性而作为属性存在。
    currentState:对于开关设备,用 boolean 类型表示当前开关状态(true 表示合上,false 表示打开);对于调速器设备,可以用 int(分档调速器的当前档位)或者 double(连续调速器的当前档位参数)类型来表示当前的调节状态,初始状态按照题目要求都设为 0。
    方法:
    toggleSwitch():对于开关设备,实现切换开关状态的功能,内部修改 currentState 属性的值,实现状态的改变(currentState =!currentState)。
    adjustSpeed(String operation):针对调速器设备,接收一个表示操作的字符串参数(如 "+" 表示升档,"-" 表示降档,对于连续调速器也可以是具体的数值字符串用于设置档位参数),根据不同的设备类型(分档调速器或连续调速器)执行相应的速度调节逻辑,更新 currentState 属性的值,体现了对不同调速器操作的统一接口。
    generateOutputVoltage(double inputVoltage):根据当前设备的状态(开关的开合状态、调速器的档位等)以及输入电压,按照各自设备的规则(开关状态决定是否输出输入电压、调速器根据档位比例计算输出电压等)计算并返回输出电压值,模拟了控制设备对电压的处理逻辑。
  3. 受控设备类(ControlledDevice)
    继承关系:同样继承自 CircuitDevice 类,利用基类的基础属性,并添加受控设备特有的属性和行为。
    属性:
    pin1Voltage:double 类型,记录设备第一个引脚的电压值,用于后续根据引脚间电压差来确定设备的工作状态和相关参数(如亮度、转速等)。
    pin2Voltage:double 类型,记录设备第二个引脚的电压值,与 pin1Voltage 配合使用。
    resistance:double 类型,存储设备的电阻值,按照题目给定的不同设备电阻(如白炽灯电阻为 10,日光灯电阻为 5 等)进行初始化,用于后续可能涉及到的包含电阻的电路计算(在后续迭代中会用到)。
    方法:
    setPinVoltages(double pin1Voltage, double pin2Voltage):用于设置设备两个引脚的电压值,方便在电路连接和电压传递过程中更新设备引脚的电压情况,外部可以通过该方法告知设备当前的电压输入情况。
    calculateStatus():根据两个引脚间的电压差以及设备自身的特性(如白炽灯根据不同电压差确定亮度,风扇根据电压差确定转速等),按照题目给定的规则计算并更新设备的内部状态(例如亮度值、转速值等),是实现受控设备根据电路电压情况做出响应的核心方法。
    displayStatus():重写基类的 displayStatus 方法,按照输出格式要求展示设备当前的状态信息(如灯的亮度、风扇的转速等),实现了多态展示受控设备状态的功能。
  4. 串联电路类(SeriesCircuit)
    属性:
    devices:List 类型,用于存储构成该串联电路的所有电路设备对象,按照从电源端到接地端的顺序依次添加,方便后续模拟电压在串联电路中的依次传递等操作。
    circuitId:String 类型,标识该串联电路的编号,用于区分不同的串联电路,遵循题目中串联电路编号的格式要求。
    方法:
    addDevice(CircuitDevice device):向串联电路中添加一个电路设备对象,将其添加到 devices 列表末尾,实现串联电路设备的组装功能,便于构建具体的串联电路结构。
    simulateVoltageFlow(double inputVoltage):模拟电压在串联电路中的流动过程,从输入电压开始,按照顺序依次调用每个电路设备的 generateOutputVoltage 方法(对于控制设备)或者 setPinVoltages 方法(对于受控设备),传递电压并更新各设备的引脚电压情况,最终返回经过串联电路后的输出电压,实现了串联电路中电压传递和对设备作用的模拟功能。
    displayCircuitStatus():遍历 devices 列表,调用每个设备的 displayStatus 方法,按照顺序输出串联电路中所有设备的状态信息,方便展示整个串联电路中各设备的状态情况,符合题目要求的输出格式和顺序。
  5. 并联电路类(ParallelCircuit)
    继承关系:继承自 CircuitDevice 类,将并联电路也看作是一个独立的电路设备,这样可以方便地将其融入到更复杂的电路结构(如多个并联电路串联等情况,在后续迭代中会涉及)中进行统一管理和处理。
    属性:
    seriesCircuits:List 类型,存储构成该并联电路的所有串联电路对象,体现了并联电路由多个串联电路组成的结构特点。
    circuitId:String 类型,标识该并联电路的编号,与串联电路编号类似,用于区分不同的并联电路。
    方法:
    addSeriesCircuit(SeriesCircuit seriesCircuit):将一个串联电路对象添加到并联电路中,添加到 seriesCircuits 列表内,实现构建并联电路的功能,通过添加多个串联电路来组成具体的并联电路结构。
    simulateVoltageFlow(double inputVoltage):模拟电压在并联电路中的流动情况,由于并联电路各支路电压相等,对每个包含的串联电路都调用 simulateVoltageFlow 方法并传入相同的输入电压,然后综合各支路的情况(例如在后续迭代考虑电流等参数时可以进行相应计算和处理),返回经过并联电路后的输出电压,实现了并联电路中电压传递的模拟以及对各串联支路的统一处理
    功能。
    displayCircuitStatus():遍历 seriesCircuits 列表,依次调用每个串联电路的 displayCircuitStatus 方法,按照顺序输出并联电路中所有串联电路包含的设备状态信息,实现了展示整个并联电路及其内部各串联电路中所有设备状态的功能,满足题目对输出格式和顺序的要求。
    1.3类之间的协作关系
    在构建整个家居电路模拟系统时,首先创建各种具体的控制设备(开关、调速器等)和受控设备(灯、风扇等)对象,它们都是 CircuitDevice 的子类,各自初始化相应的属性,如设备编号、类型以及初始状态等。
    然后根据输入的串联电路信息,创建 SeriesCircuit 对象,通过 addDevice 方法将对应的电路设备添加到串联电路中,构建出具体的串联电路结构;对于并联电路信息,创建 ParallelCircuit 对象,并通过 addSeriesCircuit 方法将相关的串联电路添加进去,形成并联电路结构。
    在模拟电路运行时,从电源(VCC,给定电压 220V)开始,对于串联电路,调用 SeriesCircuit 的 simulateVoltageFlow 方法,让电压在串联电路中依次传递并作用于各设备,设备根据自身逻辑(控制设备处理电压输出,受控设备根据电压差计算状态)进行响应;对于并联电路,调用 ParallelCircuit 的 simulateVoltageFlow 方法,使得电压在各并联支路(串联电路)中传递并处理,最终完成整个电路的电压传递和设备状态更新。
    最后,通过调用各个电路(串联电路或并联电路)的 displayCircuitStatus 方法,按照题目要求的顺序输出所有设备的状态信息,展示整个家居电路的模拟结果。

2.类图

踩坑心得

  针对第四次大作业中的答题判断4的踩坑分析:

  1. 试卷引用检查不完善
    在代码中,虽然有部分地方对试卷是否存在进行了检查,例如在以下代码片段中:
    for (Answer answer : answerList) {
    int key = answer.getPaperID();
    if (!examinationMap.containsKey(key)) {
    System.out.println("The test paper qusid does not exist");
    continue;
    }
    // 后续其他逻辑处理
    }
    这里会检查试卷编号对应的试卷是否存在于 examinationMap 中,但检查相对比较简单,只是输出提示信息后跳过当前答案的后续处理。可能在后续更复杂的逻辑中,对于试卷引用无效的情况没有全面地阻断相关的错误逻辑继续执行,导致出现不符合预期的结果。例如,如果在后续基于试卷信息进行一些计算或者展示操作时,假设试卷不存在却依然尝试去获取试卷中的题目等相关数据,就可能引发异常或者输出错误的结果。

  2. 缺乏统一的错误处理机制
    对于试卷引用无效这种错误情况,只是简单地输出提示语句,没有采用一种统一的、规范的错误处理方式,这可能导致在整个程序运行过程中,一旦出现试卷引用无效的情况,后续逻辑执行的稳定性和正确性无法得到保障,进而无法通过相关测试点的验证。

  3. 与其他功能逻辑的耦合问题
    在处理学生答案、计算成绩等相关逻辑中,与试卷引用的判断逻辑交织在一起,使得代码的可读性和维护性变差。当出现试卷引用无效的情况时,很难清晰地追踪哪些逻辑受到了影响以及是否所有相关的处理都正确地进行了错误处理或者回退操作,容易出现遗漏的情况,影响了程序在面对这种特定错误场景时的健壮性。

  4. 依赖顺序假设的处理逻辑
    代码中的一些逻辑可能隐含地假设了输入数据的顺序,就比如在处理学生答案、试卷信息以及学生信息的过程中,可能想要按照某种特定顺序先输入试卷相关内容,再输入学生相关内容,最后输入答案相关内容等。但对于多试卷多学生乱序输入的情况,这种基于顺序的处理逻辑就会出现问题。就比如:
    for (Answer answer : answerList) {
    int key = answer.getPaperID();
    // 查找对应的学生信息等逻辑
    Pupil pupil = new Pupil(-1, ""); int symbol = 0; for (Pupil stu : pupilList) { if (answer.getPupilID() == stu.getPupilID()) { symbol = 1; pupil = stu; break; } } // 后续基于试卷、学生、答案的处理逻辑 }
    如果学生信息和答案信息的输入顺序不符合预期,可能会导致在查找对应学生信息时出现找不到的情况(即使学生实际存在,只是因为输入顺序问题还未被正确添加到 pupilList 中),进而影响后续整个答题结果的处理和展示逻辑,导致输出不符合要求,无法通过测试。

  5. 数据关联和匹配逻辑的脆弱性
    在处理多个试卷、多个学生以及他们之间的关联(通过试卷编号、学生编号等建立联系)时,代码中对于数据的匹配和关联逻辑不够健壮。当出现乱序输入时,难以准确地将学生的答案对应到正确的试卷以及正确的学生个体上,可能出现张冠李戴的情况,使得最终计算成绩、展示结果等功能出现错误。例如,在根据答案中的试卷编号查找试卷信息以及根据学生编号查找学生信息时,没有充分考虑乱序输入带来的影响,没有足够的机制来确保数据之间的准确匹配和关联,从而影响了程序对这种复杂输入场景的应对能力。

踩坑心得总结

  1. 输入验证与错误处理要全面且规范
    对于程序接收的各种输入数据,无论是试卷信息、学生信息还是答案信息等,都要进行全面细致的验证,不仅仅是简单地检查格式是否正确,还要对数据之间的关联性(如试卷引用是否有效、学生与答案是否能准确对应等)进行严格校验。同时,要建立统一规范的错误处理机制,通过抛出合适的异常等方式,让程序在出现错误时能够明确告知调用者具体的错误情况,方便进行针对性的处理,而不是简单地输出提示信息后任由程序继续执行,可能导致更复杂难以排查的错误出现。
  2. 避免顺序依赖
    在设计程序逻辑时,要尽量避免依赖输入数据的特定顺序来保证功能的正确性。代码的逻辑应该基于数据本身的关联性和内在的业务规则来编写,而不是假设用户会按照某种固定顺序输入数据。如果确实需要一定的顺序,可以在程序开始处对输入数据进行整理排序,或者通过更清晰的标识和匹配机制来确保无论输入顺序如何,都能正确地处理数据之间的关系,提高程序对不同输入顺序情况的适应性和健壮性。

不同功能模块(如试卷管理、学生管理、答题结果处理等)之间的逻辑应该尽量解耦,避免相互之间高度依赖和复杂的交织,这样当出现某一类型的错误(如试卷引用无效)时,能够清晰地定位到受影响的代码范围,方便进行针对性的修改和完善。同时,提高代码的可读性也很重要,通过合理的命名、清晰的代码结构以及适当的注释等方式,让代码逻辑易于理解,便于后续排查问题以及对程序进行维护和优化,以应对各种复杂的测试场景和实际使用情况。
4. 考虑复杂场景并提前设计应对机制
在开发程序时,不能仅仅满足于对常规输入情况的功能实现,要充分考虑到可能出现的各种复杂场景,像本题中的乱序输入情况。在设计阶段就应该提前规划好相应的应对机制,例如设计合适的数据结构和算法来处理乱序数据、增加额外的标识或状态来辅助数据的准确匹配等,这样可以避免在后期测试或者实际应用中才发现程序无法应对这些复杂情况,减少返工和修改代码的成本,提升程序的整体质量和实用性。
总之,通过这次遇到的测试点未通过的情况,深刻认识到在编写代码时要从多方面考虑程序的健壮性、对不同输入场景的适应性以及代码的可维护性等因素,避免踩到类似的 “坑”,确保程序能够稳定可靠地运行并满足各种需求。

针对第五次大作业家电程序-1的踩坑分析

在 IncandescentLightApparatusType 类中,用于设置白炽灯亮度值的 setBrightnessValue 方法里,虽然对几个特殊电压值(如 0 - 9、10、220)对应的亮度做了明确处理,但对于其他中间电压值的亮度计算逻辑可能不够准确。特别是在模拟分档情况时,如果期望是按照一定的规则分档来确定亮度,当前代码只是简单地通过线性比例计算中间值亮度(基于 (entryDianYa - 9) / (220.0 - 10) 这个比例来计算),可能没有考虑到实际分档的具体细节要求,例如分档边界情况、舍入规则等与预期分档逻辑不一致,导致最终计算出的亮度值不符合正确答案要求。
例如代码中的这部分逻辑:
if (entryDianYa >= minRange && entryDianYa <= maxRange) {
brightnessLevelValue = 0;
} else if (entryDianYa == 10) {
brightnessLevelValue = specialValueAtTen;
} else if (entryDianYa == 220) {
brightnessLevelValue = specialValueAtTwoTwenty;
} else if (entryDianYa > 9 && entryDianYa < 220) {
double ratio = (entryDianYa - 9) / (220.0 - 10);
brightnessLevelValue = (int)(baseValueForIntermediate + ratio * rangeForIntermediate);
}
对于分档情况,可能需要更精细地划分不同电压区间对应不同的固定亮度档位,而不是简单的线性比例计算。

与其他设备交互时的电压传递影响
整个程序通过 VoltageProcessor 类来模拟电压在各个设备间的传递,对于分档白炽灯来说,它接收到的输入电压是经过前面控制设备(如开关、调速器等)处理后的电压。如果在前面控制设备对电压的处理逻辑(例如开关的开合状态、调速器的档位调节等)存在错误或者不符合预期的情况,那么传递到白炽灯的电压就不正确,进而导致根据该电压计算出的亮度值也是错误的。
比如在 VoltageProcessor 类中的这段电压传递代码:

for (HomeElectricalApparatus e : apparatusList) {
switch (e.apparatusType) {
case "K":
entryDianYa = ((SwitchApparatusType) e).generateOutputVoltage(entryDianYa);
break;
case "F":
entryDianYa = ((SpeedRegulatorApparatusType) e).generateOutputVoltage(entryDianYa);
break;
case "L":
entryDianYa = ((ContinuouslyAdjustableApparatusType) e).generateOutputVoltage(entryDianYa);
break;
}
}
如果开关没有正确地控制电压通断,或者调速器输出的电压不符合分档白炽灯预期的输入电压范围及分档逻辑,都会影响最终白炽灯亮度计算的准确性。

  1. 代码结构与功能模块划分不清晰:整个代码虽然按照设备类型、命令处理、电压处理等功能划分了不同的类,但在类内部的方法职责划分可能不够清晰。例如在 VoltageProcessor 类中,既处理了电压在设备间的传递逻辑,又包含了根据电压设置不同设备状态的逻辑,功能较为复杂且耦合度较高。如果后续需要对电压传递逻辑或者设备状态设置逻辑进行单独修改或扩展,可能会影响到类中其他相关逻辑,增加代码出错的风险。应该进一步细化类内部方法的职责,降低功能模块之间的耦合度,提高代码的可维护性和扩展性。
    比如说可以把 VoltageProcessor 类中原本混合在一起的电压传递逻辑和根据电压设置设备状态的逻辑拆分开,分别封装到不同的方法中,使每个方法专注于一个明确的功能职责。这样一来,当后续需要对其中某一个功能进行修改或扩展时,能够更方便地定位和操作相应代码,而不会影响到另一个功能相关的逻辑,降低出错的风险。
    class VoltageProcessor {
// 单独的方法用于处理电压在设备间的传递逻辑
public static double transferVoltageAmongApparatus(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap) {double entryDianYa = 220;LinkedList<HomeElectricalApparatus> apparatusList = new LinkedList<>(apparatusMap.values());// 遍历设备列表,根据设备类型模拟电压的传递for (HomeElectricalApparatus e : apparatusList) {switch (e.apparatusType) {case "K":entryDianYa = ((SwitchApparatusType) e).generateOutputVoltage(entryDianYa);break;case "F":entryDianYa = ((SpeedRegulatorApparatusType) e).generateOutputVoltage(entryDianYa);break;case "L":entryDianYa = ((ContinuouslyAdjustableApparatusType) e).generateOutputVoltage(entryDianYa);break;}}return entryDianYa;
}// 单独的方法用于根据传递后的电压设置不同设备的状态
public static LinkedList<HomeElectricalApparatus> setApparatusStatesBasedOnVoltage(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap, double finalVoltage) {LinkedList<HomeElectricalApparatus> apparatusList = new LinkedList<>(apparatusMap.values());// 再次遍历设备列表,根据设备类型和输入电压设置设备的状态for (HomeElectricalApparatus e : apparatusList) {switch (e.apparatusType) {case "B":((IncandescentLightApparatusType) e).setBrightnessValue(finalVoltage);break;case "R":((FluorescentLightApparatusType) e).setBrightnessValue(finalVoltage);break;case "D":((FanApparatusType) e).setRotationSpeedValue(finalVoltage);break;}}return apparatusList;
}
public static LinkedList<HomeElectricalApparatus> processVoltage(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap) {double finalVoltage = transferVoltageAmongApparatus(apparatusMap);return setApparatusStatesBasedOnVoltage(apparatusMap, finalVoltage);
}

}
踩坑心得总结
编写代码过程中要时刻关注代码的可维护性和扩展性,精心设计代码结构,合理划分功能模块,明确每个方法的职责,降低模块之间的耦合度,使代码易于理解、修改和扩展,这样在面对不断变化的需求和功能迭代时,才能更高效地进行代码维护和开发工作。
总之,通过完成这个题目,从多个方面积累了宝贵的经验教训,对后续处理类似复杂的编程任务在功能实现、问题排查以及代码质量把控等方面都有很好的指导作用,提醒自己要更加严谨、全面地思考和编写代码。
针对第六次大作业的家居电路程序-2的踩坑分析

连接信息解析复杂:输入的连接信息格式较为复杂,使用正则表达式解析的时候出错 在处理 引脚组合以及不同引脚之间的分隔时,正则表达式的模式匹配不准确,导致引脚提取错误,影响后续对设备连接关系的构建和电压传递计算。

并联电路连接逻辑混淆:对于并联电路的连接逻辑理解不够清晰,尤其是在处理多个串联电路组成并联电路时,如何正确地合并引脚连接关系、确定电压在并联分支中的分配等方面容易出现错误。

将过多的设备连接处理逻辑和电压计算逻辑都放在一个类中,当需要对某个功能进行修改或扩展时,会影响到其他相关功能,增加代码出错的风险,并且不利于代码的维护和阅读。

踩坑心得总结
1.
在开始编写代码之前,要对对家居电路模拟的业务规则进行深入细致的分析和理解。包括各种设备的特性、工作原理、连接方式、状态转换条件以及输入输出格式等。只有对这些规则有清晰的把握,才能在代码实现过程中准确地翻译业务需求,避免因对业务理解偏差而导致的各种错误。
2.
根据题目特点,选择合适的数据结构来存储设备信息、连接关系等数据。例如,可以使用图数据结构来表示电路中设备的连接关系,以便更方便地进行电压传递计算和设备遍历。
3.
编写代码过程中要遵循严谨的编程规范,注重代码的可读性和可维护性。对于复杂的逻辑部分,添加详细的注释,方便自己和他人理解代码意图。同时,要进行全面的测试,包括单元测试、集成测试和边界测试等。针对不同类型的设备、各种连接情况以及控制命令组合,编写大量的测试用例,尽可能覆盖所有可能的情况,及时发现并修复代码中的漏洞。例如,测试开关在不同初始状态下切换命令的执行结果,以及不同电压输入下受控设备的状态变化是否符合预期等。

改进建议

1.针对答题程序-4的改进

目前代码虽然按照不同概念划分了多个类,如 Matter 及其子类用于表示题目,Examination 类处理试卷相关信息等,但部分类职责不够清晰明确,存在功能重叠的情况。
ScannerParser 类承担了过多不同类型输入的解析工作,各种解析方法堆积在一起,代码显得臃肿且复杂,一旦某个输入格式发生变化或者需要新增一种输入格式,整个类都可能需要大面积修改,可维护性较差。
拆分 ScannerParser 类,按照输入类型创建多个独立的解析器类,例如 QuestionParser 负责解析题目相关输入(包含普通题、多选题、填空题等),TestPaperParser 专门解析试卷信息输入,StudentAnswerParser 和 StudentInfoParser 分别处理学生答案和学生信息的输入解析。这样每个类职责单一,代码的可读性和可维护性都会大大提高,也方便针对不同输入类型进行单独的功能扩展和错误处理优化。

在 Main 类中有一段代码用于验证试卷总分是否为 100 分,目前的实现方式是遍历 examinationMap 中的每个试卷对象,调用 calculateFullPoint 方法计算总分并与 100 进行比较,如果不相等则输出提示信息。这种方式功能上可以实现验证,但代码放在 Main 类的主流程中,使得主流程的逻辑不够清晰,而且验证逻辑相对独立,与其他业务逻辑(如学生答案处理、成绩计算等)关联性不强,混合在一起不利于代码的维护和扩展。
将试卷总分验证逻辑抽取到一个独立的方法中,比如在专门的数据验证类中创建一个 validateExaminationTotalScore 方法,接收 examinationMap 作为参数,在该方法内部完成对所有试卷总分的验证,并输出相应的提示信息。这样代码结构更加清晰,主流程专注于核心的业务逻辑(如输入解析后的数据处理和结果输出等),而数据验证作为一个独立的功能模块,方便单独进行测试和维护。

目前 printResults 方法的代码结构是基于现有的题目类型(多选题、填空题等)和输出格式要求编写的,如果后续需要增加新的题目类型或者改变输出格式规则(比如增加更多的答题状态标识、调整成绩的显示格式等),现有的代码可能需要进行较大幅度的修改,可扩展性不足。
考虑采用更灵活的设计方式来应对可能的变化,例如可以定义一个接口(如 QuestionResultPrinter),不同的题目类型实现这个接口并提供各自的答题结果输出方法,在 printResults 方法中根据题目类型调用相应的实现类方法来输出答题结果,这样当新增题目类型时,只需创建新的实现类遵循接口规范实现输出逻辑即可,无需大面积修改现有的 printResults 方法代码,提高代码的可扩展性。

遵循更规范、表意清晰的变量命名原则,使用有意义的英文单词或词组来命名变量,而不是拼音和英文组合 杂乱无章的命名。

2.针对家居电器程序-1的改进建议

整体上我按照不同的电器设备类型和功能划分了多个类,如各类电器设备类(SpeedRegulatorApparatusType、SwitchApparatusType 等)以及负责命令处理、电压处理的类,这种划分有一定合理性,但部分类的职责可以更纯粹、细化。
例如,VoltageProcessor 类中既包含了电压在设备间传递的逻辑,又有根据最终电压设置各设备状态的逻辑,功能较为复杂,不利于代码的维护和扩展,如果后续需要单独修改电压传递规则或者设备状态设置的逻辑,可能会影响到类中的其他部分。
各个电器设备类中,有些属性的定义和初始化方式稍显随意,比如在 IncandescentLightApparatusType 类中,亮度计算相关的多个常量(minRange、maxRange 等)直接在 setBrightnessValue 方法中定义,若后续这些常量需要根据不同场景调整,在多个方法中查找和修改会比较麻烦,而且代码的复用性也较差。
对于 VoltageProcessor 类,可将电压传递和设备状态设置这两个主要功能拆分成两个独立的方法,甚至可以考虑进一步抽象出专门的电压传递类和设备状态更新类,使每个类专注于一项核心职责,降低耦合度,提高可维护性和扩展性。例如:

class VoltageTransfer {
public static double transferVoltage(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap, double initialVoltage) {
// 实现电压在设备间传递的逻辑,返回最终传递后的电压
double currentVoltage = initialVoltage;
LinkedList apparatusList = new LinkedList<>(apparatusMap.values());
for (HomeElectricalApparatus e : apparatusList) {
switch (e.apparatusType) {
case "K":
currentVoltage = ((SwitchApparatusType) e).generateOutputVoltage(currentVoltage);
break;
case "F":
currentVoltage = ((SpeedRegulatorApparatusType) e).generateOutputVoltage(currentVoltage);
break;
case "L":
currentVoltage = ((ContinuouslyAdjustableApparatusType) e).generateOutputVoltage(currentVoltage);
break;
}
}
return currentVoltage;
}
}

class ApparatusStateSetter {
public static void setApparatusStates(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap, double finalVoltage) {
LinkedList apparatusList = new LinkedList<>(apparatusMap.values());
for (HomeElectricalApparatus e : apparatusList) {
switch (e.apparatusType) {
case "B":
((IncandescentLightApparatusType) e).setBrightnessValue(finalVoltage);
break;
case "R":
((FluorescentLightApparatusType) e).setBrightnessValue(finalVoltage);
break;
case "D":
((FanApparatusType) e).setRotationSpeedValue(finalVoltage);
break;
}
}
}
}

目前 CommandHandler 类中对命令的解析处理逻辑覆盖的情况不够全面,只考虑了基本的几种命令格式(如开关切换、调速器加档 / 减档、连续调速器设置参数),对于一些可能的错误输入情况或者扩展的命令格式没有进行很好的处理。例如,如果输入的命令中调速器的操作符(+、-)位置不对、连续调速器设置参数的格式不符合要求(如参数不是合法的数字等),代码可能会出现异常或者得到错误的处理结果。
对于命令中设备编号的验证不够严谨,只是简单判断在 apparatusMap 中是否存在该编号对应的设备,如果存在就执行相应操作,没有进一步验证设备编号与命令对应的设备类型是否一致,可能导致逻辑错误,比如用开关的编号去执行调速器的操作命令等情况。

完善命令格式的校验逻辑,针对每种命令类型(#K、#F、#L 等)详细分析可能出现的错误格式,增加更多的条件判断来确保输入命令的合法性。例如,对于 #F 命令,可以进一步判断 +、- 操作符后面是否还有其他多余字符,对于 #L 命令严格验证参数是否是符合要求的数值(可以使用正则表达式或者 try-catch 块结合 Double.parseDouble 来判断是否能正确转换为数字)等。
在根据设备编号获取设备对象并执行操作前,添加设备类型验证逻辑,确保命令对应的设备类型与实际从 apparatusMap 中获取的设备类型一致。例如在处理 #F 命令时:

if (command.startsWith("#F")) {
String fCommand = command.substring(1, command.length());
int index1 = fCommand.indexOf("F");
int index2 = fCommand.indexOf("+");
int index3 = fCommand.indexOf("-");
if (index2 > 0) {
String f1 = fCommand.substring(index1, index2);
if (apparatusMap.containsKey(f1)) {
HomeElectricalApparatus apparatus = apparatusMap.get(f1);
if (apparatus instanceof SpeedRegulatorApparatusType) {
((SpeedRegulatorApparatusType) apparatus).speedLevelValue++;
} else {
System.out.println("命令对应的设备类型不符,无法执行操作");
}
}
} else if (index3 > 0) {
String f2 = fCommand.substring(index1, index3);
if (apparatusMap.containsKey(f2)) {
HomeElectricalApparatus apparatus = apparatusMap.get(f2);
if (apparatus instanceof SpeedRegulatorApparatusType) {
((SpeedRegulatorApparatusType) apparatus).speedLevelValue--;
} else {
System.out.println("命令对应的设备类型不符,无法执行操作");
}
}
} else {
System.out.println("Wrong Format");
}
}

还有就是要提供代码的可读性和可维护性。

3.针对家居电器程序-2的改进建议
这个题目,我仍在探索中,目前无法给出好的改进建议。不过,我认为需要注意以下一些事项:

电路设备类(基础类)

需定义用于标识设备的属性,比如设备标识符(如 K、F、L 等)和设备编号,以便区分不同的具体设备实例。
考虑添加引脚相关属性,例如可以用一个数据结构(如数组或者 Map)来存储不同引脚对应的连接情况或者电位值等信息,方便后续电路连接和电压计算时使用。
由于不同设备在电路中有不同状态(如开关的开 / 合状态、调速器的档位等),可定义一个通用的状态属性,根据具体设备子类再去细化其含义和取值范围。

设计获取设备标识符、编号以及引脚信息等的访问器方法(getter),方便在其他类中获取这些基础信息进行操作。
可以创建一个抽象的方法用于计算设备的输出电位,因为不同类型的设备(控制设备、受控设备等)计算输出电位的逻辑不同,在具体子类中去实现该方法的具体逻辑。

根据具体受控设备(灯、风扇等)的特点,添加对应属性。例如对于灯设备,可以添加表示亮度的属性;对于风扇设备,添加表示转速的属性等,并且这些属性的数据类型要按照题目要求(如亮度、转速等用 double 类型保存用于中间计算)来定义。
由于不同的受控设备有不同的工作电压区间、对应状态变化等情况,可添加相应属性来记录这些特定的参数信息,便于后续在状态计算方法中使用。

重写父类中计算输出电位的抽象方法,按照不同受控设备(如白炽灯、日光灯、吊扇、落地扇等各自的电压 - 亮度 / 转速对应关系)来实现具体的计算逻辑,确保输出电位的计算符合题目给定的规则(如比例关系、区间对应关系等)。
设计方法用于根据输入电位更新设备的状态(如亮度、转速等),这个方法会在电路电压传递和计算过程中被调用,以实时反映设备状态的变化。

针对不同控制设备(开关、分档调速器、连续调速器)的特性,添加专属属性。例如开关添加表示开关状态(0 或 1)的属性;分档调速器添加表示当前档位的属性;连续调速器添加表示档位参数(范围在 [0.00 - 1.00])的属性等,并且注意属性的初始值设置要符合题目要求(初始状态 / 档位为 0)。

同样重写计算输出电位的抽象方法,按照开关、分档调速器、连续调速器各自的输出电位规则(如开关的状态决定输出电位是否等于输入电位、分档调速器根据档位输出相应比例的输入电压、连续调速器按档位参数计算输出电压等)来编写具体逻辑。
对于开关设备,创建切换开关状态的方法(实现状态的取反操作);对于分档调速器,创建增加档位和降低档位的方法;对于连续调速器,创建设置档位参数的方法,这些方法要遵循题目给定的操作格式和规则,方便在处理控制设备调节信息时调用。

需要有一个数据结构(如列表或者数组)来存储串联电路中包含的各个电路设备对象,以便后续遍历这些设备进行电压传递和电路相关计算。
可以添加表示电路编号的属性,用于唯一标识不同的串联电路,方便在输入信息处理以及后续的电路连接、输出等操作中进行区分。

设计方法用于向串联电路中添加电路设备,确保设备按照从电源到接地的顺序依次添加(遵循输入信息的顺序要求),同时在添加过程中可以进行一些合法性校验(如不考虑调速器串联到其他调速器的情况等约束条件)。
创建方法用于计算整个串联电路的总电阻,根据串联电路中各个设备的电阻(题目中已给定不同设备的电阻值)进行累加计算,该方法在后续涉及电流计算(后续迭代需求)等情况时会用到。
实现方法来模拟电压在串联电路中的传递过程,按照设备在电路中的顺序,依次调用各个设备的计算输出电位方法,将上一个设备的输出作为下一个设备的输入,最终得到串联电路的输出电位,传递给后续连接的电路或者接地等情况。

定义一个数据结构(如列表)来存储其所包含的串联电路对象,体现并联电路由多条串联电路组成的结构特点。
同样添加表示电路编号的属性用于唯一标识,便于在输入处理、电路连接以及输出环节进行区分和操作。

设计方法用于向并联电路中添加串联电路,添加时要遵循题目给定的约束条件(如本次迭代不考虑并联电路中包含并联电路的情况等)进行合法性校验,保证添加的串联电路符合要求。
实现方法来计算并联电路的总电阻,根据并联电路电阻计算公式(1/R总 = 1/R1 + 1/R2 +... + 1/Rn,其中 R1、R2 等为各串联电路的电阻),通过调用所包含串联电路的总电阻计算方法来得到并联电路的总电阻,该属性在后续涉及电流计算等场景会用到。
创建方法模拟电压在并联电路中的传递情况,由于并联电路各支路两端电压相等,需要根据各串联电路的电阻以及总输入电压(电源电压等情况),按照并联电路电流分配等原理,计算各串联电路的输入电压,再调用各串联电路的电压传递方法来完成整个并联电路的电压传递过程,最终得到并联电路的输出电位并传递给后续电路。

对于输入的设备标识(如 K、F、L 等)和设备编号组合,要严格按照格式要求进行校验,确保输入的合法性,例如设备编号必须是数字且符合相应的编号规则(题目中未明确详细编号规则,但要保证能正确区分不同设备个体),对于不符合格式的输入要给出明确的错误提示信息(便于用户知道具体哪里输入有误)。
针对引脚格式(设备标识 - 引脚编号)也要进行细致校验,确认引脚编号的取值范围符合预期(如控制设备引脚编号为 1、2,受控设备引脚编号也为 1、2 等),同时要保证引脚对应的设备标识是已定义过的合法设备,避免出现不存在的设备引脚输入情况。

根据解析后的设备信息,创建对应的设备对象(调用相应设备类的构造函数),并将其存储到合适的数据结构中(如 Map,可以用设备标识 + 编号作为键,设备对象作为值,方便后续根据输入的操作信息快速查找对应的设备进行处理)。

对于用 [] 括起来的连接信息,要按照格式要求检查引脚之间用空格分隔是否正确,同时验证每个引脚的格式是否符合前面提到的设备引脚格式要求,若格式有误,输出相应错误提示。
处理连接信息时,要遵循题目给定的约束条件,例如不考虑调速器串联到其他调速器的情况,要在解析过程中进行判断,如果出现不符合约束的连接情况,进行相应的错误处理或者提示。

根据解析后的连接信息,将对应的设备引脚进行连接操作,在代码中体现为更新相关设备对象的引脚连接属性(例如在设备类中定义的引脚连接相关的数据结构里记录与之相连的其他引脚信息等),以便后续在电路计算和电压传递过程中能准确获取连接关系进行相应操作。

针对不同类型控制设备(开关、分档调速器、连续调速器)的调节信息格式,要严格进行格式校验。例如开关调节信息必须是 #K + 设备编号 的格式,分档调速器调节信息要符合 #F + 设备编号 + "+" 或 "-" 的格式,连续调速器调节信息要满足 #L + 设备编号 + ":" + 数值 的格式,对于不符合的输入及时输出错误提示信息告知用户格式错误位置。
对于连续调速器调节信息中的数值部分,要验证其是否是合法的 double 类型数值,并且范围在 [0.00 - 1.00] 之间(含两位小数),不符合要求的数值输入要进行相应处理(如提示错误等)。

解析出控制设备调节信息对应的设备对象后(通过前面存储设备对象的数据结构查找),按照不同的调节操作类型(切换开关、调速器加档 / 减档、设置连续调速器档位参数等),调用对应设备对象的相应方法(如开关的切换开关状态方法、调速器的档位调整方法等)来执行具体的调节操作,确保操作的正确性和符合题目规则。

对于串联电路信息(格式为 #T + 电路编号 + ":" + 连接信息 + " " + 连接信息 +... + " " + 连接信息),要校验电路编号的唯一性(不同的串联电路信息编号不同),检查连接信息的格式和顺序是否符合要求(从电源端到接地端顺序、每个连接信息的格式正确等),不符合格式的要给出错误提示。
对于并联电路信息(格式为 #M + 电路编号 + ":" + "[" + 串联电路信息 + " " +.... + " " + 串联电路信息 + "]"),同样要验证电路编号唯一性,检查所包含的串联电路信息是否都已在之前输入(遵循并联信息所包含的串联电路信息都在并联信息之前输入的约束条件),以及整个格式是否正确,若有问题及时提示错误。

根据解析后的串联电路信息,创建串联电路对象,将对应的连接信息中的设备添加到串联电路对象中(调用串联电路类的添加设备方法),构建出完整的串联电路结构,并存储到合适的数据结构中(如列表或者 Map,方便后续处理并联电路以及整个电路的连接和计算等操作)。
对于并联电路信息,创建并联电路对象,将解析出的串联电路对象添加到并联电路对象中(调用并联电路类的添加串联电路方法),形成完整的并联电路结构,同样存储好以便后续进行整个电路的组装和计算等操作,并且在组装过程中要遵循题目给定的各种约束条件(如不考虑多个并联电路串联、不考虑并联电路中包含并联电路等情况)进行合法性校验,避免出现不符合要求的电路结构。

尽量将不同功能的代码划分到不同的类和方法中,例如输入解析相关的逻辑放在专门的输入处理类或方法中,电路计算相关功能封装在电路相关的类方法里,输出相关操作独立成输出处理模块等,使得代码结构清晰,各部分职责明确,便于后续的维护、扩展以及调试。

不同类之间通过合理定义接口来进行交互,例如电路设备类可以定义一些通用的接口方法供其子类实现,串联电路类与并联电路类之间通过接口规范彼此调用的方法(如获取电阻、传递电压等方法),这样可以降低类之间的耦合度,提高代码的可扩展性和可维护性,方便在后续迭代(如电路结构变化、增加新电路元件等情况)时进行代码的修改和功能扩展。

总结

通过这三次大作业,我学到了通过继承来扩展类功能,像 ManySelectMatter 和 TianKongMatter 类继承自 Matter 类,它们复用了父类的基本属性和方法,同时又可以根据自身代表的不同题型(多选题、填空题)来进行特定的处理,体现了继承在代码复用和业务逻辑细分方面的优势。
在 WorkoutOutput 类的 printResults 方法中,通过判断 question 实例属于不同的子类(ManySelectMatter、TianKongMatter 等)来执行不同的逻辑,展示了多态性的应用,即根据对象的实际类型来决定调用哪个类中重写的方法,使得代码可以灵活应对多种题型的评判需求。
以及将整个程序划分为不同功能模块和层次的重要性与优势。
例如,将输入处理、电路计算、设备状态更新以及输出处理等功能分别封装在独立的类或方法中,形成清晰的功能模块划分。这种模块化设计使得每个部分的功能职责明确,代码结构更加清晰易读,方便开发人员进行独立开发、测试与维护,降低了代码的复杂性和耦合度。当需要对某个功能进行修改或扩展时,只需关注对应的模块,而不会对其他无关部分造成影响,极大地提高了代码的可维护性和可扩展性。
也体会到在系统架构设计中,各模块之间通过合理定义接口进行交互的必要性。比如电路设备类定义通用的接口方法供其子类实现,串联电路类与并联电路类之间通过规范的接口来实现相互调用(如获取电阻、传递电压等操作),这样的接口设计方式有效地解耦了不同模块之间的依赖关系,使得整个系统的架构更加灵活、稳健,能够更好地适应未来可能的功能变更和需求扩展,为系统的长期演进奠定了良好的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/839939.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

团队作业5——测试与发布

团队作业5——测试与发布这个作业属于哪个课程 <计科22级34班>这个作业要求在哪里 <作业要求>这个作业的目标 完成连续七天的项目冲刺GitHub 链接 https://github.com/tangliweiwww/ChatGpt团队 1.团队名称:Elegance 2.团队成员姓名 班级 学号唐立伟(组长) 计科…

Java中定时任务实现方式及源码剖析

概述 在企业级应用开发场景中,定时任务占据着至关重要的地位。比如以下这些场景:用户4个小时以内没有进行任何操作,就自动清除用户会话。 每天晚上凌晨自动拉取另一个业务系统的某部分数据。 每隔15分钟,自动执行一段逻辑,更新某部分数据。类似的场景会频繁出现在我们的日…

001 增肌锻炼

三分化https://www.bilibili.com/video/BV1mY411Y7FR 推拉腿休 推拉腿休...推力日:胸 肩 三头拉力日:背 二头每周同一部位练习2次动作:腹肌https://www.bilibili.com/video/BV1Vh4y197aD https://www.bilibili.com/video/BV1hd4y1f76Z 腹肌激活30S上腹拉伸来自为知笔记(Wiz)…

docker 存储卷实验

需求:创建1个myvolume1的空卷,将其挂载给web1的容器,挂载目录/usr/local/apache2/htdocs 运行两个web2 web3的容器,更新web2中容器内容为 This is a test! 通过宿主机访问web3查看输出内容。docker volume create myvolume1 docker run -d --name web2 -p 82:80 -v myvolum…

让何同学翻车的项目是什么来头?

‍ 背景 最近, B 站知名 UP 主何同学(1207 万粉丝)因涉嫌抄袭开源项目 ASCII generator​ 而引发争议。 视频《我用 36 万行备忘录做了个动画…》从 11 月 15 号发布,获得几百万播放,热度相当高。 他提到团队专门写了一个软件,但实际上该软件基于越南开发者 vietnh1009 在…

selenium模块,web自动化,元素定位

1. 元素定位 查看网页元素 右键-->检查from selenium.webdriver.common.by import By # 元素定位包# 使用 test.find_element(By.XXX) 1)定位元素ID--对应浏览器id# 定位一个元素 a = test.find_element(By.ID, value="wrapper") print(a) # 定位多个元素(返回列…

22207321-王郅坚-BLOG2

前言 这三次题目集涉及了不同的知识点、编程技巧及而算法逻辑,从简单的基础题目逐步过渡到复杂的业务逻辑模拟。三次题目集不仅是单单考核独立的编程任务,其实它们有明确的迭代关系,逐步递进并且不断添加复杂度。题目集1是针对前三次的题目再进行迭代升级,题目集2开始了一个…

ffmpeg 时基转换

1:av_q2d(AVRational a)函数av_q2d(AVRational);该函数负责把AVRational结构转换成double,通过这个函数可以计算出某一帧在视频中的时间位置 timestamp(秒) = pts * av_q2d(st->time_base); 计算视频长度的方法: time(秒) = st->duration * av_q2d(st->…

2024-2025-1学号20241309《计算机基础与程序设计》第九周学习总结

作业信息这个作业属于哪个课程 2024-2025-1-计算机基础与程序设计这个作业要求在哪里 2024-2025-1计算机基础与程序设计第九周作业这个作业的目标|作业正文|2024-2025-1学号20241309《计算机基础与程序设计》第九周学习总结 教材学习内容总结 《计算机科学概论》第十章: (一)…

docker网络互通实验

需求:创建两个自定义容器,分别使用自定义网络,使其互通1. 创建容器 docker run -d --name web1 -p 80:80 httpd 2. 创建网络 docker network create --driver bridge --subnet 192.168.1.0/24 net1 docker network create --driver bridge --subnet 171.16.1.0/24 net2 …

Windows下命令行及Java+Tesseract-OCR对图像进行(字母+数字+中文)识别,亲测可行

第一步:下载Tesseract OCR引擎安装包 访问Tesseract的GitHub发布页面(https://github.com/tesseract-ocr/tesseract)或第三方下载站点(https://digi.bib.uni-mannheim.de/tesseract/),下载适合你操作系统的版本(最新版本)。 推荐使用第三方下载:第二步:详细阐述一下第…

海思 uboot 编译

用默认配置烧录:本文来自博客园,作者:封兴旺,转载请注明原文链接:https://www.cnblogs.com/fxw1/p/18564721