四至六次大作业总结
一、前言
1. 7-3 答题判题程序-4
1.1 知识点
1.1.1 类设计和封装:
- 题目类:增加选择题和填空题的设计,新增题目类型这个属性,需要完成多答案解析与比对,增加答案部分正确性的判断方法。
- 试卷类:允许多试卷信息的输入,需要试卷总分校验方法,允许动态调整分值规则。
- 答卷类:新增处理多选题和填空题答案的方法,支持对部分正确答案的评分规则,增加按学号和试卷号排序功能。
1.1.2 输入解析:
- 选择题解析:新增解析包含多答案的选择题格式,正确答案以空格分隔,支持多个同学、多张试卷的答卷处理,按学号和试卷号优先级输出。
- 填空题解析:新增解析答案包含多个可接受文本的填空题格式。
- 动态解析顺序:需要确认输入信息顺序无关,允许乱序输入试卷、题目、答题等信息,统一归类解析。
- 删除题目解析:需要能正确处理题目删除指令,动态调整对应的输出内容。
1.1.3 判题逻辑:
- 单选与填空题:按答案匹配。
- 多选题判分:区分完全正确、部分正确和错误情况,按规则计分。
- 题目状态检测:对于引用错误、题目删除或答案缺失的情况优先输出提示信息。
1.2 题量
- 1.2.1 基本题量:需要有单选题、多选题、填空题以及传统题目的解析与判题逻辑。
- 1.2.2 实现内容:实现多种题型的解析、多答案比对、输出排序以及异常处理。
1.3 难度
- 很复杂和困难:需要灵活实现复杂输入解析和多场景判题逻辑,涵盖异常处理与多类型数据整合输出。
2. 家居强电电路模拟程序设计-1
2.1 知识点
2.1.1 类设计与封装:
- 设备类设计:针对不同类型的电路设备(如开关、调速器、灯具和风扇等),需要设计相应的类来封装每个设备的状态与行为。每个设备类应包含输入和输出电压,以及通过控制信号调整设备状态的方法。
- 电路连接类:连接类应支持解析输入的连接信息并根据设备间的关系更新设备状态。
- 电路管理类:此类负责电路中各个设备的状态管理与更新。根据设备的连接信息,计算电压、电流等电路参数,并根据控制指令实时更新电路状态。
2.1.2 输入解析:
- 设备与引脚输入解析:输入信息中包含设备的连接信息和引脚的连接方式,需要通过解析设备标识符和引脚编号,建立设备之间的连接关系。
- 控制指令解析:需要解析设备控制指令,根据指令改变设备的状态。开关类的控制指令用于改变开关的状态;调速器类的控制指令用于调整调速器的档位;灯具和风扇的控制则根据电压差进行计算和更新。
2.1.3 判定逻辑:
- 开关控制逻辑:开关的开/关状态直接决定电路是否通电,影响其他设备的电压输入。需要根据开关的状态判断电路是否闭合,并相应更新电路中其他设备的输入电压。
- 调速器控制逻辑:调速器的档位决定输出电压的比例。根据档位的调整,调速器的输出电压应按照预定的规则进行调整,并传递给下游设备。需要考虑到调速器输入端的电压与档位的关系,精确计算输出电压。
- 设备响应逻辑:根据电压变化来计算灯具的亮度、风扇的转速等设备的状态。不同设备对电压的响应不同,例如白炽灯的亮度随电压差成比例变化,而风扇的转速也与电压差成正比。在输出时,需根据设备的输入电压来计算其响应结果。
2.2 题量
- 2.2.1 基本题量:本题包含多个设备和连接方式,涉及控制设备与受控设备的交互。题目要求实现对电路连接、设备状态变化以及控制指令的处理。设计时要考虑设备类型、设备编号、连接规则等因素,确保电路模型的正确性。
- 2.2.2 实现内容:本题需要实现设备与电路连接的管理、设备控制指令的解析、设备状态更新等功能。要保证程序能够正确处理输入格式,准确模拟电路行为,并根据设备的电压和控制指令输出相应的状态。
2.3 难度
- 比较难:题目要求实现一个家居电路的模拟程序,涉及设备的控制逻辑、电路的连接与电压计算。尽管题目相对基础,只有串联电路,但涉及的设备种类较多,控制逻辑复杂,需要编写合理的判定和计算逻辑。
3. 家居强电电路模拟程序-2
1.1 知识点
1.1.1 类设计与封装:
- 电路类:包括了多种电路设备(如开关、分压器、连续调节器等)的管理与状态更新功能。通过多层次的封装设计,支持电路设备的增删、串联电路与并联电路的计算与管理。
- 电路设备类:每个电路设备都是一个类(如
Switch
、DividerGovernor
、ContinuousGovernor
等),拥有各自的属性与方法,封装了设备的状态、控制指令与电压、电流的计算逻辑。 - 电路连接管理:通过串联电路(
seriesCircuits
)与并联电路(parallelCircuits
)的组织方式,模拟了电路设备间复杂的连接关系,实现了串联与并联电路的计算逻辑。 - 控制指令处理:设计了控制信息解析与设备控制的功能,允许用户通过输入不同的控制指令(如开关、调节器设置等)对设备进行状态修改。
1.1.2 输入解析与动态调整:
- 控制指令解析:对不同类型的控制指令(如开关操作、分压器调节等)进行解析,处理控制命令对电路设备的影响,支持动态的控制指令输入。
- 电路设备连接解析:支持串联和并联电路设备的输入解析,处理不同类型的电路设备间的连接关系,确保电路状态的准确更新。
- 异常处理与设备状态检测:对于电路设备中的异常(如开关未闭合、分压器设置为零等),能够进行错误检测并适时输出提示信息。对电路中的短路、断路等情况也进行了相应的处理与判断。
1.1.3 电路计算与判定:
- 电阻计算:设计了并联电路与串联电路的电阻计算方法,能够根据电路设备的状态和连接关系动态计算电阻,并更新电流、电压等电路状态。
- 电流与电压分配:根据总电压(如220V)和各个电路设备的电阻,计算整个电路的电流,并根据电压降和电阻情况,更新各个设备的电压状态。
- 电路状态检测:通过
updateDevices
方法更新所有电路设备的状态,动态调整电路的工作状态,并且输出每个设备的当前状态。
1.2 题量
1.2.1 基本题量:需要实现电路中多种设备的模拟与多电路连接关系的计算。每种设备的设计需要满足模拟电路中复杂的操作与控制功能。
1.2.2 实现内容:通过对多种设备的模拟、电路状态的动态调整、输入指令的解析与电路计算等功能的实现,构建了一个较为完整的电路系统模拟器。电路的计算涉及串联与并联电路的电阻计算、电流分配、电压变化等内容,并能根据用户输入控制电路设备的开关与调节。
1.3 难度
非常难:该项目增加了并联电路处理,难度直线上升。
二、设计与分析
7-3 答题判题程序-4
1.1 类图设计
1.2 SourceMonitor 报表分析
- 项目目录:
D:\Desktop\PTA4CODE\
- 项目名称:PTA4
- 检查点名称:Baseline
- 文件名称:
PTA4code.java
- 代码行数:286 行
- 语句数:244 个语句
- 分支语句百分比:19.7%,表示代码中分支语句(如
if
,switch
等)占总语句的比例。 - 方法调用语句:132 个方法调用语句。
- 代码注释百分比:0.3%,表示代码中注释行占总行数的比例。
- 类和接口数:10,表示该文件中定义了 10 个类或接口。
- 每类方法数:2.50,表示平均每个类中定义了 2.50 个方法。
- 每方法平均语句数:7.20,表示平均每个方法包含 7.20 个语句。
- 最复杂方法的行号:185 行,表示
ExamSystem.parseInput()
方法是最复杂的方法。 - 最大复杂度:10,表示代码中方法的最大复杂度为 10。
- 最深代码块的行号:123 行,表示最深代码块的行号。
- 最大代码块深度:4,表示代码块的最大嵌套深度。
- 平均代码块深度:1.98,表示平均代码块深度。
- 平均复杂度:2.74,表示所有方法的平均复杂度。
- 方法分布:最复杂方法在 1 个类中。
1.3 代码分析
1.3.1 类职责分工
- Main 类:程序的入口,初始化
ExamSystem
实例,并通过控制台输入读取测试数据,输出结果。 - Question 类:抽象类,所有题目的基类,封装题目基本信息(题号、内容、答案等),并定义子类需要实现的题目格式化和得分方法。
- SingleChoiceQuestion 类:继承自
Question
类,表示单选题,提供题目格式化和得分的实现。 - MultipleChoiceQuestion 类:继承自
Question
类,表示多选题,提供题目格式化和得分的实现,支持部分正确的得分计算。 - FillInBlankQuestion 类:继承自
Question
类,表示填空题,提供题目格式化和得分的实现,支持部分正确的得分计算。 - QuestionFactory 类:用于根据输入字符串创建对应的题目对象,支持单选题、多选题和填空题的创建。
- TestPaper 类:表示试卷对象,管理试卷中的题目及其分值,提供验证试卷总分是否为 100 分的功能。
- Student 类:表示学生对象,包含学生的 ID 和姓名。
- AnswerSheet 类:表示学生的答卷,包含学生的答案数据。
- ExamSystem 类:核心类,负责处理整个考试系统的流程,包括解析输入、管理试卷和答卷、评分和输出结果。
1.3.2 功能分析
-
输入读取:通过
Scanner
类从控制台读取输入,读取题目、试卷、学生信息及答卷。输入格式包括题目类型(#N:
,#Z:
,#K:
)、试卷信息(#T:
)、学生信息(#X:
)以及答卷信息(#S:
)。 -
解析题目和答案:
- 通过正则表达式解析题目输入行,分离出题号、题目内容和标准答案。不同类型的题目(单选、多选、填空)使用不同的类进行处理。通过
QuestionFactory
工厂类创建相应的题目对象。
- 通过正则表达式解析题目输入行,分离出题号、题目内容和标准答案。不同类型的题目(单选、多选、填空)使用不同的类进行处理。通过
-
创建试卷对象 TestPaper:试卷通过题目顺序和分值来定义,使用
Map
存储题目的分数和顺序。每个试卷对象会绑定一定数量的题目,并通过TestPaper
类管理。 -
创建答卷对象 AnswerSheet:答卷保存学生的答案,并与试卷中的题目顺序对应。
AnswerSheet
类通过addAnswer
方法添加学生的每道题答案。 -
判题:
- 每道题目通过
getFormattedQuestion
方法格式化输出,显示学生的答案和判题结果。 getScore
方法用来计算学生答案的得分,支持单选题的完全正确、部分正确和错误的判定;多选题和填空题也同样支持部分正确的判定。
- 每道题目通过
-
结果展示:
- showQuesAndAns:输出每道题目的内容和学生提供的答案,并判断答案是否正确。
- showResults:输出每道题目的判题结果(如
true
、partially correct
或false
),并计算学生的总分。
-
错误处理:对输入格式不正确的情况进行错误处理并记录错误日志,确保系统对不规范输入具有容错性。
2. 家居强电电路模拟程序设计
2.1 类图设计
2.2 代码报表分析
- 项目目录:
D:\Desktop\PTA5CODE\
- 项目名称:PTA5
- 检查点名称:Baseline
- 文件名称:
PTA5.java
- 代码行数:425 行
- 语句数:213 个语句
- 分支语句百分比:21.1%,表示代码中分支语句占总语句的比例。
- 方法调用语句:105 个方法调用语句。
- 代码注释百分比:19.8%,表示代码中注释行占总行数的比例。
- 类和接口数:2,表示该文件中定义了 2 个类或接口。
- 每类方法数:14.50,表示平均每个类中定义了 14.50 个方法。
- 每方法平均语句数:6.34,表示平均每个方法包含 6.34 个语句。
- 最复杂方法的行号:40 行,表示
CircuitManager.parseInput()
方法是最复杂的方法。 - 最大复杂度:4,表示代码中方法的最大复杂度为 4。
- 最深代码块的行号:43 行,表示最深代码块的行号。
- 最大代码块深度:4,表示代码块的最大嵌套深度。
- 平均代码块深度:0.98,表示平均代码块深度。
- 平均复杂度:2.33,表示所有方法的平均复杂度。
2.3 代码分析
2.3.1 类职责分工
-
Main 类:程序入口,负责初始化
CircuitManager
实例并通过控制台输入读取电路连接和控制命令数据,最后调用方法执行电路状态计算和输出结果。 -
CircuitManager 类:核心类,负责电路的设备管理与操作。解析输入的连接信息,处理设备间的连接,解析控制命令并处理设备状态,同时进行电压传播,计算设备的输出电压或状态(如亮度、转速等)。
-
circuitEquipment 类:所有电路设备的基类,包含输入电压(
IV
)和输出电压(OV
)属性。所有设备类都继承自此类,定义基本的电压设置和获取方法。 -
controlEquipment 类:继承自
circuitEquipment
类,增加了一个gear
属性表示设备的档位,用于表示控制设备(如开关、调速器)不同状态。 -
circuitSwitch 类:继承自
controlEquipment
,表示开关设备,包含控制开关的状态(如开启或关闭)和计算输出电压的方法。 -
binningGovernor 类:继承自
controlEquipment
,表示分档调速器,通过档位控制输出电压,并包含对档位的修正功能。 -
continuousGovernor 类:继承自
controlEquipment
,表示连续调速器,通过百分比档位设置电压,并计算输出电压。 -
controlledEquipment 类:继承自
circuitEquipment
,表示受控设备(如灯具、风扇),包含具体设备的操作逻辑(如亮度或转速的计算)。 -
light 类:继承自
controlledEquipment
,表示灯具,定义了亮度计算方法。 -
incandescentLamp 类 和 fluorescentLamp 类:分别表示白炽灯和日光灯,继承自
light
类,计算各自的亮度。 -
ceilingFan 类:继承自
controlledEquipment
,表示吊扇,通过电压计算转速。
2.3.2 功能分析
-
输入解析:通过
Scanner
类读取控制台输入,分离连接信息(设备的连接)和控制命令。连接信息通过processConnections
方法解析,设备间的连接关系被提取出来并建立设备之间的电压传递关系。控制命令通过正则表达式解析,执行设备状态的变更(如开关切换、调速器调整等)。 -
设备创建与连接:在
processConnections
方法中,通过解析连接信息,程序根据设备标识符(如K
、F
、L
等)创建对应的设备对象,并根据设备引脚(如VCC
、GND
)来初始化电压源(如输入电压或接地)。设备之间通过连接信息建立联系,并通过connectDevices
方法将设备连成电路。 -
控制命令处理:在
processCommands
方法中,通过正则表达式解析不同类型的控制命令(如#K
切换开关、#F
调整分档调速器、#L
设置连续调速器的档位)。这些命令会触发设备状态的更新,并计算输出电压。 -
电压传播与计算:
propagateVoltage
方法负责电压的传播过程。首先会遍历所有开关设备,计算每个开关的导通状态,判断是否有断开电路的情况。如果电路断开,后续设备的电压会被设置为 0。如果电路通畅,电压会从输入设备传播到后续设备,计算每个设备的输出电压、亮度、转速等参数。 -
输出设备状态:通过
outputStatus
方法,程序会按照设备类型(如开关、灯具、风扇等)和设备编号顺序输出设备的状态。状态包括开关的开启/关闭状态、调速器的档位、灯具的亮度或风扇的转速等。
2.3.3 代码结构分析
-
设备类设计:电路设备通过类继承实现多态,每个设备类根据设备类型的不同实现自己的特定功能(如计算电压、亮度或转速等)。这种设计方式使得代码具备高度的可扩展性和可维护性,可以方便地新增设备类型。
-
控制命令处理:使用正则表达式解析输入命令,并根据命令类型调用相应的方法来处理设备状态。这种方式简洁高效,但需要保证输入格式的准确性,否则会导致解析失败。
-
电压传播逻辑:电压传播通过遍历所有设备,并根据设备的类型和状态进行不同的处理。开关设备的状态会影响后续设备的电压传递,确保电路状态的准确模拟。调速器和灯具的输出会根据输入电压动态计算,确保电压变化的合理性。
2.3.4 程序优化建议
-
输入验证:目前的代码假设输入格式始终正确,应添加更多的输入校验逻辑,避免因输入错误导致程序崩溃或行为异常。
-
性能优化:虽然该程序的功能较为简单,但在设备数量较多时,遍历设备的次数会增加。可以使用更高效的图结构来表示设备间的连接关系,从而提高电压传播和设备状态更新的效率。
3.家居强电电路模拟程序-2
3.1 类图设计
3.2 SourceMonitor 报表分析
- 项目目录:
D:\Desktop\PTA6CODE\
- 项目名称:PTA6
- 检查点名称:Baseline
- 文件名称:
PTA6.java
- 代码行数:800 行
- 语句数:497 个语句
- 分支语句百分比:27.6%,表示代码中分支语句占总语句的比例。
- 方法调用语句:171 个方法调用语句。
- 代码注释百分比:10.6%,表示代码中注释行占总行数的比例。
- 类和接口数:9,表示该文件中定义了 9 个类或接口。
- 每类方法数:5.22,表示平均每个类中定义了 5.22 个方法。
- 每方法平均语句数:10.43,表示平均每个方法包含 10.43 个语句。
- 最复杂方法的行号:289 行,表示
Circuit.parallelResistance()
方法是最复杂的方法。 - 最大复杂度:19,表示代码中方法的最大复杂度为 19。
- 最深代码块的行号:311 行,表示最深代码块的行号。
- 最大代码块深度:8,表示代码块的最大嵌套深度。
- 平均代码块深度:2.41,表示平均代码块深度。
- 平均复杂度:3.45,表示所有方法的平均复杂度。
3.3 代码分析
3.3.1 类职责分工
- Main 类:程序的入口,初始化
CircuitSystem
实例,读取输入并展示模拟电路的状态。 - Device 类:抽象类,所有电路设备的基类,封装设备的基本信息(如名称、电压、电流等)和状态(开关、分压等)。定义子类需要实现的设备控制方法和电路计算方法。
- Switch 类:继承自
Device
类,表示开关设备。控制设备的开启与关闭,影响电路的整体状态。 - DividerGovernor 类:继承自
Device
类,表示分压器。控制电压的分配,影响电路中的电压计算。 - ContinuousGovernor 类:继承自
Device
类,表示连续调节器。调节电流或电压,影响电路中的电流和电压分布。 - Circuit 类:管理电路中各个设备的连接(串联与并联),并计算电路的电阻、电流和电压。
- CircuitSystem 类:核心类,负责管理电路设备的创建、连接、更新和计算,控制整个电路系统的模拟流程。
- InputParser 类:用于解析输入指令,将用户输入的电路设备、控制指令、连接信息等转换为相应的对象或操作。
3.3.2 功能分析
-
输入解析:
- 通过
Scanner
类从控制台读取输入,读取设备信息、连接指令、控制指令等。输入格式包括设备定义(如Switch: A
)、电路连接(如Connect: A-B
)和控制操作(如SwitchOn: A
)。
- 通过
-
设备管理:
- 通过
InputParser
解析输入的设备信息,创建电路设备(如开关、分压器等)。每个设备都封装了自己的属性与状态。
- 通过
-
电路连接:
- 电路连接通过
Circuit
类管理,支持串联与并联连接。不同的设备通过电路连接起来,共享电压、电流与电阻等计算结果。
- 电路连接通过
-
设备控制:
- 电路设备(如
Switch
、DividerGovernor
等)可以通过控制指令进行开启、关闭或调节,影响电路中的电流和电压分布。
- 电路设备(如
-
电路计算:
- 电路通过
Circuit
类进行电阻、电流与电压的计算。对于串联电路,电阻相加;对于并联电路,电阻的倒数相加。计算时,设备的开关状态会影响电流分配。
- 电路通过
-
结果展示:
- 使用
showStatus()
方法输出每个设备的当前状态(如是否开启、调节的电压等)。 - 使用
showCircuitStatus()
输出整个电路的状态,包括总电流、电压分配和各设备的工作状态。
- 使用
-
错误处理:
- 对输入格式不规范的情况进行错误提示,确保系统在出现非法输入时能够稳定运行。比如,设备连接时若设备不存在或连接错误,系统会输出错误信息并跳过该操作。
-
电路状态更新:
- 电路系统能够动态更新各个设备的状态,通过
CircuitSystem.updateDevices()
方法计算电流和电压分配,并根据电路设备的控制状态(开关、调节等)重新计算电路的总电流和电压。
- 电路系统能够动态更新各个设备的状态,通过
三、采坑心得
1. 7-3 答题判题程序-4
1.1 题目解析中的正则表达式问题
在实现题目解析时,我初期使用了简单的 String.split
方法来分割题目内容和答案。但是由于题目和答案中可能包含空格或其他特殊字符,在解析时出现了两个问题:
- 问题 1:如果题目内容或答案中包含空格,
split
方法会将整个字符串分割成多个部分,导致无法正确获取题目内容或答案。例如,在题目#N:1 #Q: This is a question #A: correct answer
中,split
会错误地分割答案部分,导致数据丢失。 - 问题 2:题目顺序和输入顺序可能不一致,导致在提取题目时,题目的顺序没有按照题号正确排列。
解决方案
为了解决这个问题,我改用了正则表达式来解析题目内容和答案,从而确保能够准确提取包含空格的题目和答案。具体代码如下:
String pattern = "#N:(\\d+) #Q:(.*?) #A:(.*)";
Matcher matcher = Pattern.compile(pattern).matcher(quesInput);
if (matcher.matches()) {
int qNum = Integer.parseInt(matcher.group(1).trim());
String qText = matcher.group(2).trim();
String qAns = matcher.group(3).trim();
// 创建题目对象
QuestionItem qItem = new QuestionItem(qNum, qText, qAns);
paper.addQues(qItem);
}
这里的正则表达式 #N:(\\d+) #Q:(.*?) #A:(.*)
通过非贪婪匹配 .*?
来避免过多的分割,能够准确提取题号、题目内容和答案,即使内容中含有空格或其他特殊字符。
题目顺序问题:为了解决题目顺序问题,我对题目列表进行排序,确保题目按题号顺序输出:
qList.sort(Comparator.comparingInt(QuestionItem::getQNum)); // 按题号排序
这样可以确保即使输入的题目顺序不正确,最终输出时依然是按题号排列的。
1.2 答案解析的顺序对齐问题
在初始实现中,我直接按照输入顺序对比题目和答案,而没有考虑题目编号与答案顺序可能不一致的问题。这导致在某些测试用例中,答案与题目顺序对不上,出现了错误。例如,输入如下:
#N:2 #Q:1+1= #A:2
#N:1 #Q:5+5= #A:10
#A:10 #A:2
虽然答案顺序是按照 #A:10 #A:2
输入的,但题号应该为 1 的答案是 10,题号为 2 的答案是 2。由于直接按顺序对比,程序无法正确匹配题目和答案。
解决方案
为了解决这个问题,我通过题号来对齐题目和答案,而不是依赖输入顺序。我创建了一个 Map<Integer, String>
来映射题号与答案,并确保题号对应正确的答案。具体代码如下:
Map<Integer, String> ansMap = new HashMap<>();
List<QuestionItem> qList = paper.getAllQues();
for (int i = 0; i < qList.size(); i++) {
QuestionItem qItem = qList.get(i);
int qNum = qItem.getQNum();
ansMap.put(qNum, ansList.get(i)); // 使用题号作为键,答案作为值
}
2. 家居强电电路模拟程序设计-1
2.2 电压传播问题
在实现电压传播功能时,我遇到了如下问题:
- 问题 1:设备之间的电压传播顺序不一致,导致电压传递的结果并不如预期。例如,如果一个设备的输入电压为 0,但它仍然尝试对后续设备进行电压传播,结果导致后续设备的电压状态出错。
- 问题 2:电路断开时,后续设备应该没有电压,但如果没有正确标记电路断开,可能会出现设备仍然继续传播电压的错误。
解决方案
为了解决这些问题,我设计了电压传播的过程时加入了一个标志位来标记电路是否断开,并在传播过程中按正确的顺序更新每个设备的电压状态。如果电路断开,则后续设备的电压应为 0。最重要的是,我添加了对开关设备的检查,确保在开关处于关闭状态时电路不会继续传播电压。具体实现如下:
public void propagateVoltage() {
double voltage = inputVoltage; // 初始电压为VCC电压
boolean circuitOpen = false; // 标记电路是否断开
for (String deviceId : deviceOrder) {
circuitEquipment device = equipments.get(deviceId);
if (device instanceof circuitSwitch) {
circuitSwitch sw = (circuitSwitch) device;
sw.calOV();
if (sw.getGear() == 0) {
circuitOpen = true; // 电路断开
break;
}
}
}
if (circuitOpen) {
voltage = 0;
}
for (String deviceId : deviceOrder) {
circuitEquipment device = equipments.get(deviceId);
if (voltage == 0) {
device.setIV(0);
} else {
device.setIV(voltage);
}
if (device instanceof circuitSwitch) {
((circuitSwitch) device).calOV();
} else if (device instanceof binningGovernor) {
((binningGovernor) device).calOV();
} else if (device instanceof continuousGovernor) {
((continuousGovernor) device).calOV();
}
voltage = device.getOV();
}
}
3. 家居强电电路模拟程序-2
3.1 心得体会
这道题加入了并联电路处理,直接给我打蒙了,原来写的电路设备类设计几乎都不可用了,原来的类设计用的电压是输入电压和输出电压两个,发现这个电压适用于控制设备,但是对于受控设备,用这个电压属性来计算压降非常困难,但我死守这个设计,一直没有正确处理并联电路后跟着的串联电路的分压问题,导致大半测试点通不过。一开始没意识到这个问题,只觉得自己的类设计没有标号,参考了一下同学的类设计之后就接着开发了,导致后续问题频发,并造成58分惨案。痛定思痛,决定这周要重写类设计重做这题!!!
四、改进建议
1. 7-3 答题判题程序-4
1.1 抽象输入输出处理为独立模块
-
目前情况:当前代码中,输入和输出的处理逻辑与题目管理逻辑紧密耦合,在题目修改或删除时,需要同时处理输入输出的调整。
-
改进:可以将输入输出处理与题目管理的核心逻辑分离,专门创建一个
InputOutputHandler
类来负责处理所有输入输出的相关工作。这样,题目类与输入输出处理类的耦合度降低,程序结构更加清晰,便于后续维护和扩展。 -
改进方法:
class InputOutputHandler {
public String readInput() {
// 读取并返回输入
return scanner.nextLine();
}
public void outputResult(String result) {
// 输出结果
System.out.println(result);
}
}
通过将输入输出单独封装在一个类中,程序的职责划分更加明确,便于管理和扩展。
1.1 优化题目排序与查找
-
目前情况:在当前代码中,题目和答案使用简单的集合结构进行存储,虽然能满足基本的功能需求,但在题目数量增多时,查找、排序和修改效率可能不高,尤其是在需要动态调整题目顺序时。
-
改进:为了提升数据访问效率,可以使用
TreeMap
来存储题目,这样能够自动按题号排序。 -
改进:
class QuestionManager {
private Map<Integer, Question> questions = new TreeMap<>();
public void addQuestion(int number, String text, String answer) {
questions.put(number, new Question(number, text, answer));
}
public Question getQuestion(int number) {
return questions.get(number);
}
public Collection<Question> getAllQuestions() {
return questions.values(); // 自动按题号排序
}
}
2. 电路模拟系统改进建议
2.1 抽象设备创建为独立工厂类
-
目前情况:在现有代码中,设备的创建和初始化逻辑被分散在多个地方,如
CircuitManager
类的processConnections
方法中,导致设备创建与管理逻辑高度耦合,增加了代码的复杂度和维护难度。 -
改进:可以将设备的创建逻辑抽象为一个独立的工厂类
DeviceFactory
,该类根据设备的类型来创建相应的设备实例。这样不仅可以减少CircuitManager
的代码复杂度,还能使得设备的创建更加模块化,便于后续扩展和修改。 -
改进方法:
class DeviceFactory {
public static circuitEquipment createDevice(String identifier) {
switch (identifier.charAt(0)) {
case 'K': return new circuitSwitch();
case 'F': return new binningGovernor();
case 'L': return new continuousGovernor();
case 'B': return new incandescentLamp();
case 'R': return new fluorescentLamp();
case 'D': return new ceilingFan();
default: return null;
}
}
}
然后在 CircuitManager
中使用该工厂类来创建设备:
private circuitEquipment createDevice(String identifier) {
return DeviceFactory.createDevice(identifier);
}
通过将设备创建逻辑集中到 DeviceFactory
类中,程序结构更加清晰,且如果后续需要新增设备类型,只需在工厂类中修改,无需更改其他类的代码。
2.2 优化电压传播逻辑
-
目前情况:在
CircuitManager
中,电压传播的逻辑比较集中,主要通过遍历设备和检查每个设备的状态来逐步传播电压。然而,当前的设计中,对于每个设备类型,电压传播的计算方法都是通过判断设备的类型来手动调用不同的计算方法,增加了代码重复性和复杂度。 -
改进:可以通过引入策略模式(Strategy Pattern)来优化电压传播逻辑。每种设备可以拥有自己的电压传播策略接口,具体的电压计算由不同的设备类自己实现。这样不仅提高了代码的可扩展性,还能避免
CircuitManager
类中的冗余代码。 -
改进方法:
interface VoltagePropagationStrategy {
void propagateVoltage(circuitEquipment device);
}
class SwitchVoltageStrategy implements VoltagePropagationStrategy {
public void propagateVoltage(circuitEquipment device) {
circuitSwitch sw = (circuitSwitch) device;
sw.calOV(); // 开关计算输出电压
}
}
class LampVoltageStrategy implements VoltagePropagationStrategy {
public void propagateVoltage(circuitEquipment device) {
light lamp = (light) device;
lamp.calBrightness(); // 灯具计算亮度
}
}
// 在电路设备中,设置一个策略
class circuitSwitch extends controlEquipment {
private VoltagePropagationStrategy voltageStrategy = new SwitchVoltageStrategy();
public void setVoltageStrategy(VoltagePropagationStrategy strategy) {
this.voltageStrategy = strategy;
}
public void applyVoltage() {
voltageStrategy.propagateVoltage(this);
}
}
然后,在 CircuitManager
类中,当传播电压时,依赖设备的策略来进行调用:
for (String deviceId : deviceOrder) {
circuitEquipment device = equipments.get(deviceId);
if (device != null) {
device.applyVoltage(); // 根据设备的策略传播电压
}
}
通过这种方式,电压传播的逻辑被更清晰地分离到了不同的设备策略中,每种设备的行为可以通过调整策略来改变,而无需修改 CircuitManager
中的核心代码。
2.3 优化设备状态输出逻辑
-
目前情况:在现有代码中,
outputStatus
方法每次都需要遍历不同类型的设备并打印其状态。这个方法内部包含了大量的类型判断和状态输出代码,导致逻辑重复和代码冗余。 -
改进:可以使用模板方法模式(Template Method Pattern)来优化设备状态输出逻辑。创建一个抽象的
Device
类,定义一个通用的输出状态的方法,具体的设备类只需要实现自己的状态计算逻辑。这样可以避免代码重复,并使得状态输出逻辑更加统一。 -
改进方法:
abstract class Device {
public abstract String getDeviceStatus();
}
class circuitSwitch extends Device {
public String getDeviceStatus() {
return (getGear() == 1 ? "closed" : "turned on");
}
}
class incandescentLamp extends Device {
public String getDeviceStatus() {
return String.format("%d", (int) getBrightness());
}
}
// 然后在 CircuitManager 中统一调用
public void outputStatus() {
for (String deviceId : deviceOrder) {
Device device = equipments.get(deviceId);
if (device != null) {
System.out.println("@" + deviceId + ":" + device.getDeviceStatus());
}
}
}
3. 家居强电电路模拟程序-2
3.1 58分就不提什么改进建议了
重写类设计!
五、总结
1. 重视类设计
类设计不写好,后面方法的实现可能会举步维艰,所以开始写代码之前一定要分析好后续可能会增加的需求再进行类设计。
2. 需要进一步学习软件设计模式
在面对复杂的编程任务时,应用设计模式可以极大地提高代码的可扩展性。比如工厂模式和组合模式,能够帮助我在编程项目中更加高效地解决问题。需要更深入的学习这些设计模式。
3. 对课程与教学的改进建议
课程的整体设计很好,我没有特别好的建议。对我自己而言,我需要继续多写代码,多学习知识,不断提升自己的编程能力。还有这周要重写下PTA6。