Java7-8次大作业
最后两次Java作业实现了一个智能家居电路模拟器,包括控制设备(如开关、调速器等)、受控设备(如灯、风扇、窗帘等)、电路(串联电路、并联电路)以及模拟器本身。模拟器可以处理用户输入,模拟电路的运行,并输出设备的状态。
代码结构分析
控制设备基类(ControlDevice):
·定义了控制设备的基本属性,如ID、输入引脚和输出引脚。
·包含一个抽象方法getStatus(),用于获取设备的状态。
具体控制设备类(Switch、StepRegulator、ContinuousRegulator、MutexSwitch):
·继承自ControlDevice,实现了各自的控制逻辑和状态获取方法。
受控设备基类(ControlledDevice):
·定义了受控设备的基本属性,如ID、输入引脚和输出引脚。
·包含一个抽象方法getStatus(),用于获取设备的状态。
具体受控设备类(IncandescentLamp、FluorescentLamp、CeilingFan、StandingFan、ControlledCurtain):
·继承自ControlledDevice,实现了各自的控制逻辑和状态获取方法。
电路类(SeriesCircuit、ParallelCircuit):
·SeriesCircuit类表示串联电路,包含控制设备和受控设备的列表,以及计算输出电压的方法。
·ParallelCircuit类表示并联电路,包含串联电路的列表,以及计算输出电压的方法。
智能家居电路模拟器类(SmartHomeCircuitSimulator):
·包含控制设备和受控设备的映射表,以及主电路(并联电路)。
·提供方法用于添加设备、处理输入和模拟电路运行。
类图如下:


代码时序分析

以上为大概时序图。总体思路如下:
首先,模拟器将创建各种控制设备、受控设备实例,将控制设备和受控设备分别添加到相应的映射表中;并创建串联电路和并联电路实例,将串联电路添加到并联电路中。
然后解析输入,确定操作类型(针对哪个控制设备进行何种操作)。
如果是针对某个控制设备(如Switch)的操作,模拟器与对应的控制设备进行交互。例如,对于#K1操作,模拟器会找到对应的Switch对象(假设为switch1)并调用其toggle方法。控制设备执行相应的操作并更新自身状态。
最后,模拟器遍历控制设备和受控设备的映射表,获取并输出每个设备的状态。
圈复杂度分析


在圈复杂度中,SeriesCircuit类的平均圈复杂度为5,这个值显然是不正常的,降低了代码的可读性和可维护性。
在calculateOutputVoltage方法(圈复杂度为19)中,有一个循环遍历controlDevices列表,在循环内部有多重if - else if条件判断。对于不同类型的控制设备(Switch、StepRegulator、ContinuousRegulator、MutexSwitch),都有不同的处理逻辑,这增加了代码的分支数量,从而导致圈复杂度增大。以及,在处理StepRegulator设备时,内部有一个switch语句,这也增加了代码的复杂程度,进一步提高了圈复杂度。
后续的可能改进方法
定义策略接口:
创建一个名为ControlDeviceStrategy的接口,该接口有一个方法adjustOutputVoltage(double inputVoltage)。
不同类型的控制设备(如Switch、StepRegulator、ContinuousRegulator等)分别实现这个接口。例如,SwitchStrategy实现类中,根据开关状态调整电压;StepRegulatorStrategy实现类中,根据档位调整电压等。
修改SeriesCircuit类:
在SeriesCircuit类中,将controlDevices列表的类型改为List
在calculateOutputVoltage方法中,循环遍历controlDevices列表时,直接调用每个策略对象的adjustOutputVoltage方法,而不需要复杂的if - else if判断。
提取方法:
对于处理受控设备状态更新的部分,可以将每种受控设备(如IncandescentLamp、FluorescentLamp等)的状态更新逻辑提取成独立的方法。例如,创建updateIncandescentLamp、updateFluorescentLamp等方法,在calculateOutputVoltage方法中,只需要根据设备类型调用相应的更新方法,这样可以减少主方法中的代码复杂度。
优化MutexSwitch处理:
如果在实际情况中MutexSwitch确实不影响电压,那么可以考虑从if - else if判断中移除它,或者将其处理逻辑单独放在一个方法中,避免在主计算逻辑中增加不必要的复杂度。
电路的具体代码实现
串联电路


1、结构分析
类的属性:
private List
private List
构造函数:
构造函数创建了两个空的ArrayList,分别用于初始化controlDevices和controlledDevices,这为后续添加设备提供了容器。
方法:
addControlDevice(ControlDevice device):此方法用于向controlDevices列表添加控制设备,功能简单直接。
addControlledDevice(ControlledDevice device):类似地,该方法用于向controlledDevices列表添加受控设备。
calculateOutputVoltage(double inputVoltage):这是类中的核心方法,用于根据输入电压以及电路中的控制设备和受控设备的状态来计算输出电压。
2、计算输出电压逻辑
在calculateOutputVoltage方法中,首先将outputVoltage初始化为inputVoltage。
然后通过循环遍历controlDevices列表:
对于Switch类型的控制设备,如果开关状态为关闭(!s.state),则直接将outputVoltage设置为0,这符合开关对电路的基本控制逻辑。
对于StepRegulator类型的设备,根据其step值来确定一个系数factor,然后将outputVoltage乘以这个系数,实现了对电压的分级调节。
对于ContinuousRegulator类型的设备,直接将outputVoltage乘以其value,以实现连续的电压调节。
对于MutexSwitch类型,目前代码假设它不直接影响电压(可根据实际需求调整)。
接着,通过循环遍历controlledDevices列表:
对于不同类型的受控设备,如IncandescentLamp、FluorescentLamp等,根据计算得到的outputVoltage进行相应的操作,例如计算亮度、设置速度或计算开合比例等,这反映了不同设备对电压的不同响应方式。
3、存在的问题和改进点
可维护性:
存在多个if - else if语句来处理不同类型的设备,当需要添加新的设备类型时,需要修改这个方法的内部逻辑,这违反了开闭原则,可维护性较差。可以考虑使用策略模式,将不同类型设备的处理逻辑封装到各自的策略类中。
代码复用性:
在处理不同类型受控设备时,虽然每个设备都有自己独特的操作,但其中可能存在一些可以复用的逻辑,目前代码没有体现这一点。后续可以考虑提取公共的逻辑部分到一个单独的方法或者抽象类中。
代码可读性:
由于存在较多的类型判断和不同设备的特定操作,代码整体的可读性受到一定影响。可以通过添加更多的注释来提高代码的可读性,特别是在复杂的逻辑判断部分。
异常处理:
在整个计算过程中,没有对可能出现的异常进行处理。例如,在StepRegulator的switch语句中,如果step的值不在预期范围内(0 - 3),没有相应的处理逻辑。应该添加适当的异常处理代码,以确保程序的稳定性。
并联电路

1、结构分析
类的属性:
private List
构造函数:
public ParallelCircuit() { seriesCircuits = new ArrayList<>(); }构造函数简单地初始化seriesCircuits列表,为后续添加串联电路对象做准备。
方法:
public void addSeriesCircuit(SeriesCircuit circuit)该方法用于向seriesCircuits列表中添加一个串联电路对象,功能比较直观。
public double calculateOutputVoltage(double inputVoltage):这是核心方法,用于计算并联电路的输出电压。
2、逻辑分析
在calculateOutputVoltage方法中,首先初始化totalCurrent和totalResistance为0,这两个变量分别用于累计总电流和总电阻。
然后遍历seriesCircuits列表中的每个串联电路。对于每个串联电路:
调用circuit.calculateOutputVoltage(inputVoltage)来获取该串联电路的输出电压。这里体现了代码的层次性,通过调用串联电路的方法来获取其输出电压,符合电路计算的逻辑。
假设每个串联电路的电阻固定为1(这里可根据实际需求调整),计算出该串联电路的电流current = outputVoltage / resistance。
将计算得到的电流累加到totalCurrent,电阻累加到totalResistance。
最后,根据并联电路的电压计算公式V = I * R(这里I是总电流totalCurrent,R是总电阻totalResistance),计算并返回并联电路的输出电压outputVoltage = totalCurrent * totalResistance。
3、存在的问题和改进点
电阻固定值的假设:
目前代码中假设每个串联电路的电阻固定为1,这在实际应用中可能不具有通用性。如果需要更精确的电路计算,应该将电阻作为一个变量或者从串联电路对象中获取其实际电阻值。
异常处理:
在计算过程中,没有对可能出现的异常进行处理。例如,如果某个串联电路的输出电压计算过程中出现异常(如除以0等情况),可能会导致整个并联电路的输出电压计算失败。应该考虑添加适当的异常处理逻辑。
可扩展性:
如果需要在并联电路的计算中考虑更多的电路特性或者物理量,目前的代码结构可能需要较大的改动。可以考虑采用更灵活的设计模式,如策略模式或观察者模式等,来提高代码的可扩展性。
第8次迭代
新增内容
增加管脚电压的显示:
在每个设备类中添加属性来存储管脚电压。
在calculateOutputVoltage方法中,计算并更新每个设备的管脚电压。
在输出设备状态时,同时输出管脚电压。
电流限制:
在每个设备类中添加属性来存储最大电流。
在calculateOutputVoltage方法中,计算每个设备的实时电流,并与最大电流进行比较。
如果实时电流超过最大电流,在输出设备状态时添加相应的提示。
短路检测:
在calculateOutputVoltage方法中,添加短路检测逻辑。
如果检测到短路,输出相应的提示信息,并不输出设备状态。
并联电路中包含并联:
修改ParallelCircuit类的calculateOutputVoltage方法,以支持并联电路中包含并联电路的情况。
递归计算每个并联电路的输出电压。
二极管:
添加Diode类,实现二极管的特性。
在calculateOutputVoltage方法中,添加对二极管的处理逻辑。
二极管(Diode)类具体实现

Diode类有两个属性:anodePin和cathodePin,分别代表二极管的阳极和阴极引脚。还有一个Boolean属性isForwardBiased,用于表示二极管是否正向偏置。
构造函数接受两个参数,分别是阳极引脚和阴极引脚的编号。在构造函数中,初始化isForwardBiased为false,表示二极管初始状态为反向截止。
isForwardBiased方法用于获取二极管的偏置状态。setForwardBiased方法用于设置二极管的偏置状态。getAnodePin和getCathodePin方法分别用于获取阳极引脚和阴极引脚的编号。

浙公网安备 33010602011771号