目录
前言
PTA第七次大作业总结
PTA第八次大作业总结
PTA期末测试总结
设计与分析
PTA第七次大作业的设计与分析
PTA第八次大作业的设计与分析
PTA期末测试的设计与分析
采坑心得
改进建议
总结
前言
随着期末考试的结束,这学期的Java学习也将告一段落,这篇博客是我对于pta大作业7、大作业8以及期末考试的总结与分析。
1.该题目所涉及到的知识点:
正则表达式的使用、HashMap与LinkedList及其API的使用、继承与多态、抽象类与接口以及设计模式。
2.总结:
相较与上一次的大作业,本次大作业主要添加了三个内容:1、添加了新的控制设备互斥开关,12引脚之间默认电阻为5,13引脚之间默认电阻为10;2、添加了新的受控设备窗帘,窗帘电阻为15,其打开比例受到室内灯光强度的控制;3、线路中包含多个串联起来的并联电路。 与上一次大作业相比,添加内容并不是很多,由于我之前做出了较为合理框架设计,所以不需要修改很多就能通过较多的测试点。
1.题目所涉及到的知识点:
正则表达式的使用、HashMap与LinkedList及其API的使用、继承与多态、抽象类与接口以及设计模式,函数的递归。
2.总结:
作为最后一次的大作业,相较于上一次大作业,添加了许多的内容,增加了很大难度:1、添加了一个设备二极管,其电路特性为:正向导通,反向截止;当电流从左至右流过时,二极管导通”conduction”,电阻为0;电流从右至左流动时,二极管截止”cutoff”,电阻无穷大,相当于开关打开。2、添加了电路的检测:增加管脚电压的显示、电流限制以及短路检测。3、并联电路中可以包含并联电路。从题目新增的内容上看,我们需要至少添加两个类,需要在检测电流的同时计算各个管脚的电压,难度提升了许多。
1.题目所涉及到的知识点:类的设计,继承与多态。
2.总结:
期末测试的内容较为简单,需要根据题目给的材料搭建不同种类的谷仓,计算各个类型谷仓的容积,尽量建造较大的谷仓,并对谷仓进行排序。
1、题目分析与类的设计
相较于上一次大作业,这次大作业添加了许多内容:(1)受控设备有了电阻的属性,我们要通过电阻的分压关系来判断受控设备的电压值。(2)输入的改变,输入的信息可以分为三种:串联电路信息、并联电路信息和对控制设备的操作。(3)添加了新的设备落地扇。 虽然看上去没有新添很多内容,但是由于会出现并联电路和串联电路的组合,所以用之前的通过电位差来计算电压的方法并不适用,所以我更改了设计,我决定通过电阻和电流来计算电压。除此之外,我还优化了之前类的设计,我首先在Device类中增加了新的成员电阻和电流,在控制设备类中新增了一个抽象方法Control()用于对控制设备的操控;设计了串联电路SeriesCircuit继承Device类,其中成员有存储连接关系的Map<String, String> connections和存储设备的Map<String, Device> devices,通过方法total_resistance()来计算串联电路的总阻值;设计了并联电路类ParallelCircuit继承Device类,其中成员有存储串联电路的List
2、类图

如图,我们设计了一个device类,是所有设备的父类,其成员有输入电压、输出电压、设备id,定义了两个抽象方法:更新电压updateVoltage(double voltageIn)、获取设备状态getStatus()。设计了受控设备类以及控制设备类,而开关类、调速器类继承控制设备类,日光灯、吊扇和白炽灯继承了受控设备类。通过设计Circuit电路类,来进行电路的控制,电路类中有成员Map<String, Device> devices存储电路中的设备信息;List
3、部分流程分析
输入流程

如图,首先我们一行一行地接收数据,判断每行是以什么开头,如果是以#T开头,说明接收到的是一个串联电路的数据,我们就新建一个串联设备类,调用其处理输入的函数,将串联电路中的各个设备加入自己的devices的Map中;如果是以#M开头,我就创建一个并联电路成员,调用其处理输入的方法;如果是以#end开头,说明是结束输入,我们直接结束就好;如果不是以上这些情况,说明输入的是命令,我们将命令存好即可。
计算电流与电压流程
串联电路电流计算
首先在SeriesCircuit类的updateVoltage方法中,计算串联电路的电流。通过公式current = this.voltage/this.resistance计算,其中this.voltage是串联电路的总电压,this.resistance是串联电路的总电阻。总电阻的计算在total_resistance方法中完成,它会遍历串联电路中的所有设备,根据设备类型和连接情况累加电阻值。如果遇到电阻为负(表示断路)或MutexSwitches状态异常且连接不匹配的情况,会将总电阻设为 -2(表示断路,无穷大电阻)。
计算出电流后,会遍历串联电路中的每个设备,通过device.voltage = this.current*device.resistance为设备设置电压,然后调用设备的updateVoltage方法更新设备状态。
并联电路电流计算
在ParallelCircuit类的updateVoltage方法中,会先计算并联电路的总电阻。遍历并联电路中的每个串联电路circuit,如果串联电路总电阻为 0,则表示短路,将并联电路电阻设为 0 并结束计算;如果串联电路电阻大于 0,则通过this.resistance += 1.0 / circuit.getResistance()累加其倒数,最后通过this.resistance = 1.0 / this.resistance计算出并联电路总电阻。
对于并联电路中的每个串联电路,如果其总电阻不为 0 且不是断路(总电阻小于 0 时跳过),则通过circuit.setCurrent(this.voltage / circuit.total_resistance())计算串联电路的电流,其中this.voltage是并联电路的输入电压,circuit.total_resistance()是串联电路的总电阻。接着计算串联电路的电压circuit.voltage = circuit.getResistance()circuit.getCurrent(),然后遍历串联电路中的设备,按照device.voltage=circuit.getCurrent()device.resistance设置设备电压并调用device.updateVoltage()更新设备状态。
整体电路电流计算
在Circuit类的Update_circuit_resistance方法中,先更新并联电路的电阻(通过调用parallelCircuit.total_resistance())。然后对于串联电路,如果总电阻小于 0,则将电流设为 0;否则,根据连接情况和设备类型确定输入电压,计算串联电路的电流entries.get(0).getValue().setCurrent(entries.get(0).getValue().getVoltageIn()/entries.get(0).getValue().total_resistance()),其中entries.get(0).getValue()是最外层的串联电路,getVoltageIn()是其输入电压,total_resistance()是其总电阻。最后遍历串联电路中的设备,更新设备电压和状态。
整体电路电压计算
由于串联电路和并联电路都属于设备类,我们只要遍历AllDevices这个map中的设备,并且都调用其计算电压的方法,通过我们之前几步的操作,以及知道各个设备的电流和电阻,我们只需将其相乘,就可以都得到对应的的电压了。
1、题目分析与类的设计
该题目要求我们设计一个智能家居强电电路模拟系统,其中要求我们能够实现:(1)控制设备模拟,可以通过控制开关、分档调速器、连续调速器来控制电路的状态。(2)受控设备模拟,要求我们能够根据电压来计算出受控设备的状态,受控设备包括白炽灯、日光灯、吊扇。(3)设备信息的输入,分别用设备标识符K、F、L、B、R、D分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇,引脚格式:设备标识-引脚编号,例如:K1-1标识编号为1的开关的输入引脚。根据题目分析,我们可以设计一个device类,是所有设备的父类,其成员有输入电压、输出电压、设备id,定义了两个抽象方法:更新电压updateVoltage(double voltageIn)、获取设备状态getStatus()。设计了受控设备类以及控制设备类,而开关类、调速器类继承控制设备类,日光灯、吊扇和白炽灯继承了受控设备类。通过设计Circuit电路类,来进行电路的控制,电路类中有成员Map<String, Device> devices存储电路中的设备信息;List
2、类图

如图:
设备类型枚举 DeviceType
在这个枚举中列出了各种可能的设备类型,包括开关、调速器、灯、风扇、窗帘等。每种设备类型对应一个枚举值,以便在程序中统一管理和识别不同类型的设备。
设备接口 Device
设备接口定义了所有设备类必须实现的方法:
void setPower(int power): 设置设备的输入电位差,不同设备可以根据具体需求处理这个输入电位差。
void toggleState(): 切换设备的状态,例如开关类设备切换开关状态。
具体设备类的实现
每种设备类型都有对应的类来实现 Device 接口,每个类负责处理自己特定类型设备的功能:
开关 (Switch): 控制电路的开闭状态,根据状态输出相应的电流。
分档调速器 (StepSpeedController): 提供多档位的输出电位差,可以切换不同的档位来调节输出。
连续调速器 (ContinuousSpeedController): 提供连续范围内的输出电位差,可以根据需要设置具体的位置参数。
灯 (Bulb): 控制灯的开关状态,根据灯的状态输出对应的亮度。
风扇 (Fan): 控制风扇的开关状态,根据风扇的状态输出对应的转速。
窗帘 (Curtain): 控制窗帘的开合程度,根据具体需求设置开启程度。
主函数 main
主函数负责程序的入口和整体流程控制:
创建一个 Scanner 对象用于读取输入信息。
使用 HashMap 存储设备对象,其中键为设备的唯一标识符,值为对应的设备对象。
循环读取输入信息,根据输入信息的不同类型(串联电路、并联电路、控制命令、连接信息),调用相应的方法进行处理。
每种输入类型对应一个处理方法,例如 processSeriesCircuit 处理串联电路信息,processControlInfo 处理设备控制命令等。
在处理连接信息时,调用 connectDevices 方法来连接两个设备。
设备连接和控制逻辑
连接逻辑: 在 connectDevices 方法中,根据设备的唯一标识符从 HashMap 中获取相应的设备对象,然后进行连接。这里的连接可以是物理连接(如电缆连接)或逻辑连接(如设定关联的操作)。
控制逻辑: 在 processControlInfo 方法中,根据控制命令执行相应的操作,如切换设备状态或设置设备的输入电位差。
1、题目分析与类的设计
我们设计一个材料类来存储材料相关的数据,设计一个谷仓类作为父类,设计圆柱谷仓类和四面体谷仓类继承该父类。
2、类图

如图,我们设计一个材料类来存储材料相关的数据,设计一个谷仓类作为父类,设计圆柱谷仓类和四面体谷仓类继承该父类,其中子类都实现了父类的计算体积的方法
3、部分流程分析
输入数据读取与谷仓对象创建
程序首先创建一个空的ArrayList用于存储谷仓对象,即granaries。
从控制台读取第一个双精度浮点数作为谷仓的高度height,若height小于等于 0,则输出错误格式提示并终止程序。
接着在while循环中不断读取双精度浮点数作为谷仓的长度length,只要sc.hasNextDouble()为真就继续循环。当length小于等于 0 时,跳出循环。在循环内,根据length的值创建不同类型的谷仓对象。如果length大于等于 20,创建CylinderGranary对象;如果length大于等于 15 且小于 20,创建CubeGranary对象;如果length大于等于 5 且小于 15,创建ConeGranary对象;如果length小于 5,则忽略该输入,不创建谷仓对象。创建的谷仓对象都添加到granaries列表中,并且每个谷仓对象在创建时都传入了包含height和length信息的material对象作为参数。
谷仓列表排序与体积输出
调用granaries.sort(null)对granaries列表进行排序,这里使用了默认的比较器。默认比较器是基于Granary类实现的Comparable接口中的compareTo方法,该方法通过比较谷仓的体积来确定顺序。
最后遍历排序后的granaries列表,对于每个谷仓对象,调用其getVolume方法获取体积,并使用System.out.printf("%.2f ", granary.getVolume());以保留两位小数的格式输出体积值。
1.第七次大作业中,要考虑开关放在受控设备后的情况,我在处理连接关系时,只考虑到开关放在受控设备之前的情况,导致无法通过一些测试点。
2.第七次大作业中,在读取串联电路的输入设备时,要将并联电路看作一个设备存入串联电路的设备集合中。
3.第七次大作业中,分档调速器可以有第四档,而之前只有三档,要记得修改判断条件。
4.第七次大作业中,当开关闭合时,电阻为应该设置为0,当开关断开时,电阻应该设置为无限大而不是0。
5.在第八此大作业中,要注意浮点数的精度问题,之前一直有两个测试点过不了,最后提高电阻的精度之后就能通过。
1.要养成多谢注释的习惯,在写此次博客的时候我回顾了这几次大作业的代码,发现注释寥寥无几,导致我阅读代码有些困难。
2.代码中变量命名要规范,我吸取了第四次大作业的教训,在之后的大作业中尽量规范命名,之后发现读代码时会更加流畅。
3.可以将一些抽象函数替换为接口,提高程序的可拓展性和维护性。比如我的Controller类中的Control抽象方法,可以换成接口,后续的类就不用继承Controller类了,直接实现该接口即可。
4.要注意类的单一职责原则,我在有些类中放了冗余的方法,这一点需要修改。
5.减少if-else语句的使用,尽量用其他办法来替代,比如用switch-case语句替代。
通过这两次大作业的练习,我深刻地认识到了在java中进行设计的重要性,也体会到了设计合理的类结构和继承、封装、多态的使用对于代码的迭代能提供多大的便利。我发现自己在进行类的设计时还存在许多不足之处,比如无法遵循单一职责、继承关系设计不合理等,在之后的大作业中应该要避免;除此之外,我应该多对于老师上课将的模式设计进行实践,比如在第七和第八次大作业中,我就可以使用组合模式的设计,这样可以提高代码的可拓展性。总体而言,通过这最后两次大作业,我收获了许多相关的知识,比如类的继承与多态、Map的相关API的使用等,在之后的学习中,我将继续精进自己,争取能够取得更大的进步,虽然本学期的Java课程已经结束了,但我之后会继续学习各种面向对象的技术,将从课程中学到的知识运用到之后的学习和工作中。