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作业中,虽然我的类设计能力进一步提升,但是在定义方法的规范性也需要继续改进。