1)前言
这两次作业算是一个收尾的过程,对于电路迭代的最后处理,对我来说7-8相当有难度的。7让我发现了以前设计的不少方法存在很大的问题。8则让我发现了电压处理的忽略之处。题目内容主要还是电路系统的编写与迭代。每次的新设备都是让我能意识到自己设计上的不少缺漏。
(2)设计与分析
第七次作业
家居强电电路模拟程序-3
这题在之前的基础上加上了互斥开关和受控窗帘,直接把我按地上摩擦:其中互斥开关有3个引脚:1个是汇总引脚,另两个是分支引脚,但是由于前面我只是将引脚作为一个需要记录的属性,没有给其留下足够的设计空间,所以要改的地方就有不少了,首先沿着类的属性的设计到相关的引脚方法,最后到输入输出中的相关判断,还有窗帘要根据室内灯光的光照强度来控制,这就需要将电路中灯的光强进行统计。电压处理因为设计时能将各个分电路当做设备同时记录其中各个设备的分属性,所以能够实现考虑各类设备的并联接入,故不用过多修改。
逻辑关系也可以延续前面设计的思路:
用户输入电路配置信息。, 表示创建一个串联电路。
程序解析该输入,创建 SeriesCircuit 实例并将设备 K1, K2 添加至电路。
程序运行 updateOutputVoltages() 方法,更新所有设备的输出电压。
用户可以通过键入 #K1 来切换开关状态,电路状态更新。
最后,程序输出所有设备的当前状态和相关参数。
具体的第一步设计如下:
Device(抽象类)
属性:
String id: 设备唯一标识符。
int pin: 设备引脚号。
double inputVoltage: 设备输入电压。
double outputVoltage: 设备输出电压。
double resistance: 设备电阻。
方法:
abstract void updateOutputVoltage(): 抽象方法,更新设备的输出电压。
Switch
属性:
int status: 开关状态(0=关,1=开)。
方法:
void toggle(): 切换开关状态。
String getStatusString(): 获取状态字符串(开/关)。
boolean isOn(): 判断开关是否开启。
MutualSwitch
属性:
boolean isConnectedToOutput2: 连接到输出引脚2的状态。
方法:
void toggleConnection(): 切换连接到输出。
String getStatusString(): 获取连接状态字符串。
DimmingSwitch
属性:
int gear: 调速档位(0, 1, 2, 3)。
方法:
void setGear(int gear): 设置档位。
int getGear(): 获取档位。
ContinuousDimmingSwitch
属性:
double position: 档位参数范围 [0.00 - 1.00]。
方法:
void setPosition(double position): 设置位置。
double getPosition(): 获取位置。
IncandescentLamp
方法:
double getBrightness(): 根据电压计算亮度。
FluorescentLamp
方法:
double getBrightness(): 返回固定亮度。
CeilingFan & FloorFan
方法:
double getSpeed(): 根据电压计算转速。
ControlledCurtain
方法:
int getOpenState(): 根据电压和光照强度计算窗帘开合状态。
Circuit
属性:
List
double totalResistance: 电路总电阻。
double inputVoltage: 输入电压。
方法:
void addDevice(Device device): 添加设备到电路。
void updateOutputVoltages(): 更新所有设备的输出电压。
SeriesCircuit
方法:
double getTotalResistance(): 计算串联电路总电阻。
ParallelCircuit
方法:
double getTotalResistance(): 计算并联电路总电阻。
void setInputVoltage1(double voltage): 设置并联电路的输入电压。
CircuitDevice
属性:
Circuit circuit: 包含的电路。
方法:
@Override void updateOutputVoltage(): 更新电路设备的输出电压。
CircuitSimulator
属性:
Map<String, Device> deviceMap: 设备映射,用于存储设备。
Map<String, Circuit> circuitMap: 电路映射,用于存储电路。
方法:
void processInput(String input): 处理用户输入。
void startInputLoop(): 启动输入循环。
void printDeviceStatus(): 输出设备状态。
功能流程分析
首先通过 main 方法启动程序,CircuitSimulator 类被实例化,调用 startInputLoop() 方法。
然后用户输入,startInputLoop() 方法使用 Scanner 类读取来自标准输入的内容,进入一个循环,直到用户输入 end。
每次输入都会调用 processInput(String input) 方法来处理用户的输入。
输入采集完后处理输入,用processInput(String input) 方法解析输入,并根据输入的格式调用相应的处理函数。
处理电路时识别电路类型,如果输入以 #T 开头,调用 handleSeriesCircuit(String input) 方法来处理串联电路的创建。
如果输入以 #M 开头,调用 handleParallelCircuit(String input) 方法来处理并联电路的创建。
如果输入是标准设备控制命令(例如切换开关状态),调用 handleDeviceControl(String input) 方法。
再处理串联电路
SeriesCircuit seriesCircuit = new SeriesCircuit(); // 创建新的串联电路
...
// 解析连接信息
...
// 添加设备到串联电路
...
circuitMap.put(circuitId, seriesCircuit); // 存入电路映射
}
这一方法解析了输入描述的串联电路,包括其ID和连接的设备。
为每个设备创建对应的对象,并将其存入 deviceMap。
最终将创建的串联电路对象存入 circuitMap。
同时处理并联电路
// 提取电路ID
String[] circuitIds = connections.replaceAll("[\[\]]", "").trim().split(" ");
for (String circuitIdConnected : circuitIds) {
Circuit circuit = circuitMap.get("#" + circuitIdConnected); // 获取并联电路实例
if (circuit != null) {
CircuitDevice circuitDevice = new CircuitDevice(circuitIdConnected, circuit);
parallelCircuit.addDevice(circuitDevice); // 添加到并联电路
}
}
circuitMap.put(circuitId, parallelCircuit); // 存入电路映射
}
功能类似于串联电路,但这里主要以其他已有电路作为设备来构建新的并联电路。
private void handleDeviceControl(String input) {
// 处理设备控制逻辑,比如切换开关状态等
if (input.startsWith("#")) {
String deviceId = input.substring(1); // 去掉 #
Device device = deviceMap.get(deviceId);
if (device instanceof Switch) {
((Switch) device).toggle(); // 切换开关状态
}
...
}
}
处理控制命令(如 #K1 切换开关)。它识别设备ID并改变相应的设备状态。
然后更新设备状态
用户输入完电路配置后,可以通过指令控制设备。设备状态的更新主要集中在两个地方:
开关状态改变时,通过调用 toggle 方法。
设备输出电压更新,通过遍历电路中的每个设备并调用其 updateOutputVoltage 方法。
public void updateAllDevices() {
for (Circuit circuit : circuitMap.values()) {
circuit.updateOutputVoltages(); // 更新每个电路的设备输出电压
}
}
最后是输出设备状态
程序会在每次更新后输出所有设备的当前状态,用户可以看到输出电压、亮度和转速等信息。
对于每种设备,分别输出其状态信息,如开关的状态、灯的亮度、风扇的速度等。
类图如下:
流程图如下:
第八次作业
家居强电电路模拟程序-4
这个是家居强电电路模拟程序的最后一次迭代。
首先这次迭代还是先看一下新加的电器,一个二级管,这同样是对于引脚的数据记录有一定的要求。同时需要对电路安全性的判断,这同样对于整个电路的各个部分的具体数据有很高的要求,这对于我之前的数据采集方式来说是一次不小的挑战。
然后就是在设备类里加上二级管,然后设计一个可以判断每一条通路的方法,以及对于复杂电路连接情况的处理,以及对于各设备包括被视为设备的电路的输入输出电压及电流电阻的更新和采集,,对我来说还是非常有难度的。
二级管初步设计如下:
属性
id:设备ID,用于唯一标识二极管。
pin:引脚编号,左边为1,右边为2。
inputVoltage:输入电压,记录两端的电压值。
outputVoltage:输出端的电压值,根据导通状态进行更新。
resistance:电阻值(导通时为0,截止时为无穷大)。
direction:电流流向,指示是从左至右(导通)还是从右至左(截止)。
方法
Diode(String id, int pin):构造函数,初始化id和pin,并设置默认抵抗和电压属性。
void updateOutputVoltage():根据输入电压计算输出电压。如果左引脚电压高于右引脚,设置输出电压等于输入电压,否则为0。
boolean isConducting():判断二极管是否导通;当左侧电压高于右侧电压返回true,否则返回false。
String getStatusString():返回二极管的状态描述(如“导通”或“截止”)。
类图如下:
(3)踩坑心得
第七次作业
家居强电电路模拟程序-3
引脚设计有问题:
在实现我的设计的前几次迭代的时候因为没有使用引脚所以弱化了其存在,在新一次迭代中引脚的作用重新体现了出来,所以应该重新设计相关代码。
class Diode extends Device {
private boolean isConnectedToOutput2; // 是否连接到输出引脚2
private static final double RESISTANCE_12 = 0; // 1-2引脚的电阻
private static final double RESISTANCE_13 = 0; // 1-3引脚的电阻
public Diode(String id, int pin) {
super(id, pin);
this.isConnectedToOutput2 = true; // 默认状态为连接到引脚2
}
@Override
public void updateOutputVoltage() {
if (inputVoltage > 0) {
// 根据状态决定输出电压
if (isConnectedToOutput2) {
outputVoltage = inputVoltage; // 连接到引脚2时,输出电压等于输入电压
} else {
outputVoltage = 0; // 连接到引脚3时,输出电压为0
}
} else {
outputVoltage = 0; // 输入电压为0时,输出电压为0
}
}
public boolean isConnectedToOutput2() {
return isConnectedToOutput2;
}
这样就可以初步处理引脚了。
(4)改进建议
设计还是有很多需要改进的地方,对于引脚的处理在前几次的迭代中逐渐弱化所以又得重新设计引脚相关的代码,对于电路的各个属性没有留下足够的处理空间,增加了修改的难度。还是设计的线性思路太明显了,没有足够的逻辑去支撑所有电路属性的更新,导致整个电阻的逻辑判断少了很重要的一部分,所以应该先确定整个电路的所有状态再去更新电阻。还有电路作为电路类和设备类的设计有比较大的问题,两种类的耦合性强但是设计时思路里的分工并不明确,这在最后两次复杂电路的分析里成了代码重灾区。
(5)总结
在这两次代码编写的过程中,我学到了很多,我从中深刻意识到了设计的重要性,随着增加的电路和需求慢慢变多,看到1000多行代码的我两眼一黑,代码量的提升导致设计的困难加大,冗余度提高了,同时没有很好地遵守单一职责,而是根据个人的短期思路去直接增加功能,导致代码越写越多越复杂,同时修改难度也不断加大,导致花费了大量时间去修改代码也无法完成所有基本的功能实现。
所以还是得去深入理解设计模式,学会设计的思路和方法还有性能优化技巧学会分析程序运行效率,掌握一些基础的性能调优策略,比如使用更高效的算法或数据结构。还有写代码时不能只考虑眼前的实现,还要考虑增加代码对整体设计的影响,尽量用方法去实现功能,而不是打补丁一样去做补救式的代码增加。
(6)期末总结
在这个学期的JAVA学习里我确实收获了很多,也是在大一后久违地写上了PTA,继C语言之后学习的JAVA,让我深刻感受到了OOP的魅力,各种特别的设计方式给了我不少学习的乐趣,尽管在实际的编程过程中还是被具体实现狠狠摩擦了,同时也在编码过程中不断发现自己设计思路的不足之处,语法的掌握也不断精进。所以同时老师的讲解方式也是很吸引我,老师主要讲授的设计的内容我从中也有了不少收获和思考。当然我也深深感受到了软件方向编程所需的思考和耐心,对于编码能力有限的我来说后面的迭代经常感到力不从心,但是同样在艰巨的任务中有了很快的成长和收获。真的是学到了很多。