OPP7-8次PTA大作业总结
一,前言
经过第4-6次PTA,对java中的面向对象程序设计的设计原则越来越熟悉。对于java中的单一职责原则,开闭原则,里氏代换原则等类设计原则也进一步理解其中的意义。在后续的面向对象程序设计中也了解到一些类设计模式。例如:简单工厂模式,工厂方法模式,建造者模式,单列模式等。
在7-8次PTA大作业中,我的类设计还存在些不足,以下是我对这三次PTA作业的总结。
二,第七次作业
1.
在第七次作业的要求中,在前一次作业的基础上添加了互斥开关(互斥开关设置了限流电阻,12引脚之间默认电阻为5,13引脚之间默认电阻为10。)和窗帘,而且在电路结构中添加了多个并联电路串联的情况。此次迭代和之前一样涉及到继承和多态。
以下是我的类设计思路:
在上一次PTA迭代中添加以下几种类:
添加Curtains类继继承自ControlledEquipment类(受控电器类),在窗帘类中添加SetProportion()方法,该方法调用DataHouse类获取所有白炽灯和日光灯的亮度数据,以计算窗帘的开闭程度。
添加MutexSwitch类继承自ControlEquipment类(控制设备类),在互斥开关类中添加互斥开关状态成员变量记录开关连接哪个引脚,添加pinName2和pinName3成员变量,用于记录互斥开关连接的串联电路。添加changeSwitchStatus()方法用于调节互斥开关的开闭。
2.类图
3.遇到的问题
在读取互斥开关信息时遇到如下问题:
1.互斥开关在两个串联电路信息中出现两次,原有的代码会创建两次互斥开关对象
2.互斥开关会反接到电路中,导致读取不到反接的互斥开关。
3.互斥开关可能单独接到一个串联电路中,当做普通开关使用。
4.改进
在原先的只读取一个引脚的代码加以修改,读取每一个引脚信息,再加一个if判断,如果在DataHouse中找到引脚中的电器名,则跳过,反之则创建一个对应电器的对象。特殊地,如果在DataHouse中找到互斥开关,则记录当前引脚所在的串联电路
public void CreatPerEquipment(String pin, String name, String SeriesName, SeriesElectric series) {
if ((pin.equals("2") || pin.equals("3") || pin.equals("1")) && DataHouse.findEquipment(name) == null) {
Equipment equipment = EquipmentFactory.createEquipment(name);
if (equipment instanceof MutexSwitch) {
MutexSwitch mutexSwitch = (MutexSwitch) equipment;
if (pin.equals("2")) {mutexSwitch.setPinName2(SeriesName);}
else if (pin.equals("3")) {mutexSwitch.setPinName3(SeriesName);}
}
else if (equipment instanceof SecondaryTube) {
SecondaryTube secondaryTube = (SecondaryTube) equipment;
if (pin.equals("2")) {
secondaryTube.ChangeStatus();
}
}
series.addEquipment(equipment);
DataHouse.Electrics.add(equipment);
}
else if (pin.equals("IN") && (name.startsWith("T") || name.startsWith("M"))) {
series.addEquipment(DataHouse.findEquipment(name));
}
else if (( pin.equals("2") || pin.equals("3") || pin.equals("1")) && DataHouse.findEquipment(name) instanceof MutexSwitch) {
MutexSwitch mutexSwitch = (MutexSwitch) DataHouse.findEquipment(name);
if (pin.equals("2")) {mutexSwitch.setPinName2(SeriesName);series.addEquipment(DataHouse.findEquipment(name));}
else if (pin.equals("3")) {mutexSwitch.setPinName3(SeriesName);series.addEquipment(DataHouse.findEquipment(name));}
else if (pin.equals("1")) {mutexSwitch.changePositive();}
}
}
5.缺点
在原有的的代码中添加互斥开关类和窗帘类中,需要在原有的方法中添加新的判断语句,虽然在解决问题时比较方便,但违背了面向对象类设计中的开闭原则。
三,第八次作业
1.
此次迭代中在原来基础上添加二级管,在电路结构上存在包含电路,在并联电路中的串联电路中存在并联电路包含其中的情况。
还有这次迭代还有其他要求:
1)增加管脚电压的显示
在输出每个电器的状态信息后,再依次输出该电器每个管脚的电压。(格式详见输出信息部分)
2)电流限制
电器在工作时,过大的电流会引起电器过热,从而烧坏电路。本次迭代,每个元器件都有最大电流的设置,当实时电流超过最大电流时,在该电器输出信息的最后加入提示“exceeding current limit error”,与前面的信息之间用英文空格分隔。
例如:@B1:190 68-17 exceeding current limit error
本题各类电器的最大限定电流如下:
开关20、分档调速器18、连续调速器18、白炽灯9、日光灯5、吊扇12、落地扇14、互斥开关20、受控窗帘12、二极管8。
3)短路检测
如果电路出现无穷大的电流造成短路,所有元器件信息不输出,仅输出提示“short circuit error”
类设计思路:
在上一次迭代的基础上添加SecondaryTube类继承自 ControlledEquipment类(受控设备类)
在该类中设置成员变量status记录二级管的状态,当status = "conduction"时表示二级管正接接通,
当status = "cutoff"时表示二级管反接断开。
2.类图
3.遇到的问题
由于此次迭代需要输出每个电路元件两端的电势,由于连通电路的方法中遇到断路的串联电路,就会跳过该串联电路,使得在局部断路的电路元件两端的电势都默认为零 .还有互斥开关有三个引脚,需要考虑互斥开关正接反接的问题.
问题代码如下:
public static void ConnectingCircuit() {
SeriesElectric seriesElectric = (SeriesElectric) DataHouse.A_SeriesElectric;
seriesElectric.setSumResistor();
if (seriesElectric.changeElectricCurrent() == 0 || seriesElectric.getResistor() == 0) {
return;
}
double U = 0;
double I = seriesElectric.getPinOne() / seriesElectric.getResistor();
Equipment lastEquip = null;
int i = 0;
for (Equipment equipment : seriesElectric.getEquipments()) {
i++;
if (i == 1) {
lastEquip = equipment;
if (lastEquip instanceof ContinuousGovernor || lastEquip instanceof SplitSpeedGovernor || lastEquip instanceof Switch) {
lastEquip.setPinOne(seriesElectric.getPinOne());
U = lastEquip.getPinTwo();
lastEquip.setElectricCurrent(I);
}
else {
U = seriesElectric.getPinOne();
lastEquip.setPinOne(seriesElectric.getPinOne());
lastEquip.setPinTwo(lastEquip.getPinOne() - (U * lastEquip.getResistor()) / seriesElectric.getResistor());
lastEquip.setElectricCurrent(I);
ConnectSeriesAndParallel(lastEquip);
}
}
else if (i > 1 && i < seriesElectric.getEquipments().size()) {
equipment.setPinOne(lastEquip.getPinTwo());
equipment.setPinTwo(equipment.getPinOne() - (U * equipment.getResistor()) / seriesElectric.getResistor());
lastEquip = equipment;
lastEquip.setElectricCurrent(I);
ConnectSeriesAndParallel(lastEquip);
}
else if (i == seriesElectric.getEquipments().size()) {
equipment.setPinOne(lastEquip.getPinTwo());
equipment.setPinTwo(seriesElectric.getPinTwo());
equipment.setElectricCurrent(I);
ConnectSeriesAndParallel(equipment);
}
}
}
4.改进
在ProcessingData类中添加circuitBreak()方法,该方法源码如下:
public static void circuitBreak(Equipment breakSeries) {
SeriesElectric breakSeriesElectric = (SeriesElectric) breakSeries;
double pin = breakSeriesElectric.getPinOne();
for (Equipment equipment : breakSeriesElectric.getEquipments()) {
if (equipment instanceof ContinuousGovernor || equipment instanceof SplitSpeedGovernor) {
equipment.setPinOne(pin);
pin = equipment.getPinTwo();
}
else if (equipment instanceof SeriesElectric) {
equipment.setPinOne(pin);
circuitBreak(equipment);
pin = equipment.getPinTwo();
}
else if (equipment instanceof ParallelElectric) {
ParallelElectric parallelElectric = (ParallelElectric) equipment;
parallelElectric.setSumResistor();
equipment.setPinOne(pin);
equipment.setPinTwo(pin);
ParallelConnecting(equipment);
if (parallelElectric.getResistor() == -1) {
pin = 0;
}
}
else if (equipment instanceof Switch) {
Switch switchSeries = (Switch) equipment;
equipment.setPinOne(pin);
if (switchSeries.getSwitchStatus() == 0) {
pin = 0;
}
equipment.setPinTwo(pin);
}
else if (equipment instanceof MutexSwitch) {
MutexSwitch mutexSwitch = (MutexSwitch) equipment;
if (mutexSwitch.isPassage(breakSeriesElectric.getName())) {
equipment.setPinOne(pin);
equipment.setPinTwo(pin);
}
else {
if (mutexSwitch.getPositive()) {
equipment.setPinOne(pin);
pin = 0;
mutexSwitch.setPinThree(pin);
}
else {
mutexSwitch.setPinThree(pin);
pin = 0;
mutexSwitch.setPinTwo(pin);
}
}
}
else if (equipment instanceof SecondaryTube) {
SecondaryTube secondaryTube = (SecondaryTube) equipment;
equipment.setPinOne(pin);
if (secondaryTube.getStatus().equals("cutoff")) {
pin = 0;
}
equipment.setPinTwo(pin);
}
else {
equipment.setPinOne(pin);
equipment.setPinTwo(pin);
}
}
breakSeriesElectric.setPinTwo(pin);
}
在ConnectingCircuit()(注:该方法用于连接电路传递电势)方法中如果该串联电路没有断路,则正常传递电势。如果断路则将该串联电路对象传入circuitBreak(Equipment breakSeries)方法中,在circuitBreak中进行传递断路电路的电势的操作,如断路电路中遍历到断路的开关,互斥开关或反接的二极管,则将传出的电势变为零。
5.缺点
经过多次迭代每个方法逐渐变得复杂,用到的if语句较多,还需进一步改进。
四,总结
经过这两次PTA的迭代,我对面向对象的类设计从逐渐熟悉到更加熟练的运用。在这段学习期间,也学到了许多类设计原则如组合模式,桥接模式,单例模式,工厂模式等类设计模式。我虽然了解这些类设计原则但还缺少许多实践。在PTA作业中运用的设计模式少,说明我在许多类设计模式中缺少理解,不知道某些设计模式在什么时候恰当的运用。
在四次家庭电路迭代中也让我收获了许多,电路的串并联的连接和电路结构的变化这一个抽象问题,在代码中一 一实现过程中,使我的类设计能力进一步提高。
在7-8次PTA作业中,虽然我的类设计能力进一步提升,但是在定义方法的规范性也需要继续改进。