OOP第三次Blog作业

前言

知识点

这两次的pta作业对于类之间的设计要求很高,很考验我对于类的设计。在这两次的pta作业中,都以继承作为背景,考察了对于继承中相关概念的理解。例如使用继承来扩展上一次的程序,同时加入一些特有方法和重写父类里面的一些方法;多态的使用,使用多态来调取方法时,要注意只能调取公共的方法,不能调取子类特有的方法,如果要调用子类特有的方法,那就必须使用强制类型转换,在使用强制类型转换时,最好用instanceof关键字判断该对象是不是转换后类的实例。同时依旧考察了对于使用正则表达式解析输入信息,利用解析的信息来创建对象。对于对象的储存,考察了集合相关的知识,对于数据的要求不同,要选择恰当的集合来存储元素,例如ArrayList是一个动态数组,可以灵活添加元素,而HashMap可以储存键值对,同时保证键的唯一性,对于去除重复元素可以处理。

题量和难度

题量虽然不是很大,但难度一点都不小。需要考虑的情况越来越复杂,如果没有把类设计好,那每迭代一次都要在上一次的基础上大改,这显然是很难的。

设计与分析

家居强电电路模拟程序-3

新增需求:

引入了互斥开关受控窗帘,互斥开关有三个引脚,开始时,默认1,2引脚相连窗帘打开程度受室内光照强度影响。考虑多个并联电路串联在一起的情况,本题考虑一条串联电路中包含其他串联电路的情况。

设计:

互斥开关

因为出现了互斥开关,所以先让互斥开关类继承设备类,为互斥开关新增两个数据域,一个记录引脚2所在的串联电路,另一个记录引脚3所在的串联电路,这两个数据域是服务于后续电路是否开路判断的。新的数据域如下:

String first;
String second;

因为互斥开关有三个引脚,还可能反着接,所以对于连接信息的解析做一些调整,在主函数中,拿到设备引脚信息时,判断该信息是否以H开头,如果是,则判断该引脚是2还是3,如果是1,跳过,如果是2或3,则初始化相应的数据与first或second。代码如下:

if (m.group().contains("H")) {  
    hs.put(m.group(1), (H) d);  
    int num = Integer.parseInt(m.group(2));  
    if (num == 2)  
        ((H) d).setFirst(t);  
    else if (num == 3)  
        ((H) d).setSecond(t);  
    else  
        continue;  
}

同时,还需在连接类中的判断电路状态的方法新增互斥开关判断,考虑互斥开关引脚的接入情况,如果1,2引脚相连,那么判断该连接对象的名字是不是first数据域里面保存的字符串,如果是,那么电路不是开路,处理1,3引脚也是同理。

代码如下:

public boolean isAllClose() {
    if (!allMClose())
        return false;
    int cnt = 0;
    int open = 0;
    for (Device value : sd) {
        if (value instanceof K) {
            cnt++;
            K k = (K) value;
            if (k.getIsOpen() == 1) {
                open++;
            }
        } else if (value instanceof H) {
            cnt++;
            H h = (H) value;
            if (h.first != null && h.getIsOpen() == 1 && h.first.equals(getName()))
                open++;
            else if (h.second != null && h.getIsOpen() == 0 && h.second.equals(getName()))
                open++;
        } else if (value instanceof Connection) {
            if (!((Connection) value).isAllClose())
                return false;
        }
    }
    return cnt == open;
}

受控窗帘

对于受控窗帘,先创建受控窗帘类继承设备类,给窗帘类设计一个数据域,记录所有设备中的所有灯的集合,所有类共享该数据域。同时设计一个方法,记录这些灯的亮度总和,类的设计如下:

class S extends Device {
    public static ArrayList<Device> d;
    private double iu;

    public S(int id, String name) {
        super(id, name);
        r = 15;
        compare = 9;
    }

    @Override
    public double dy(double in,double I) {
        this.iu = I * r;
        return iu;
    }

    //获得总的光照强度
    public double lightCount() {
        double sum = 0;
        for (Device device : d) {
            if (device instanceof Light) {
                sum += ((Light) device).getBrightness();
            }
        }
        return sum;
    }

    public void display() {
        double sumLight = lightCount();
        double openCount;
        if (iu < 50) {
            openCount = 1;
        } else {
            if (sumLight < 50 && sumLight >= 0)
                openCount = 1;
            else if (sumLight < 100 && sumLight >= 50)
                openCount = 0.8;
            else if (sumLight < 200 && sumLight >= 100)
                openCount = 0.6;
            else if (sumLight < 300 && sumLight >= 200)
                openCount = 0.4;
            else if (sumLight < 400 && sumLight >= 300)
                openCount = 0.2;
            else
                openCount = 0;
        }
        System.out.println("@S" + getId() + ":" + (int) (openCount * 100) + "%");
    }
}

多个并联电路串联

这个要求解决起来很简单,只需在主函数里面加点判断就行,如果是并联电路,那么不用创建对象,在并联电路集合中拿到该并联电路。

代码如下:

else if (m.group().contains("M")){
    d = sp.get(m.group(1));
}

同时,在连接类中,增加一个判断所有并联电路是否闭合的方法

代码如下:

public boolean allMClose() {
    int cnt = 0;
    int num = 0;
    for (Device device : sd) {
        if (device instanceof Paralle) {
            cnt++;
            if (!((Paralle) (device)).isOpen())
                num++;
        }
    }
    return cnt == num;
}

串联电路中包含其他串联电路

这个也是加点判断也就解决了,在主函数中,判断拿到的信息是不是以T开头

else if (m.group().contains("T")) {
    d = connections.get(m.group(1));
}

同时在判断总电路是否闭合加上判断

else if (value instanceof Connection) {
    if (!((Connection) value).isAllClose())
        return false;
}

并且,在计算总电路电阻时,也要加上判断

public double sumR() {
    double sum = 0;
    if (isAllClose()) {
        for (Device value : sd) {
            if (value instanceof Paralle)
                sum += ((Paralle) value).sumR();
            else if (value instanceof Connection)
                sum += ((Connection) value).sumR();
            else
                sum += value.r;
        }
    }
    return sum;
}

相关报表及类图

Method CogC ev(G) iv(G) v(G)
A.A(int, String) 0.0 1.0 1.0 1.0
B.B(int, String) 0.0 1.0 1.0 1.0
Connection.Connection(String) 0.0 1.0 1.0 1.0
Connection.I(double) 0.0 1.0 1.0 1.0
Connection.add(Device) 0.0 1.0 1.0 1.0
D.D(int, String) 0.0 1.0 1.0 1.0
Device.Device() 0.0 1.0 1.0 1.0
Device.Device(int, String) 0.0 1.0 1.0 1.0
Device.display() 0.0 1.0 1.0 1.0
Device.dy(double, double) 0.0 1.0 1.0 1.0
Device.getId() 0.0 1.0 1.0 1.0
Device.getName() 0.0 1.0 1.0 1.0
Device.setName(String) 0.0 1.0 1.0 1.0
F.F(int, String) 0.0 1.0 1.0 1.0
F.getCount() 0.0 1.0 1.0 1.0
H.H(int, String) 0.0 1.0 1.0 1.0
H.getIsOpen() 0.0 1.0 1.0 1.0
H.setFirst(String) 0.0 1.0 1.0 1.0
H.setSecond(String) 0.0 1.0 1.0 1.0
K.K(int, String) 0.0 1.0 1.0 1.0
K.getIsOpen() 0.0 1.0 1.0 1.0
L.L(int, String) 0.0 1.0 1.0 1.0
L.getCount() 0.0 1.0 1.0 1.0
L.setCount(double) 0.0 1.0 1.0 1.0
Light.Light(int, String) 0.0 1.0 1.0 1.0
Light.getBrightness() 0.0 1.0 1.0 1.0
Light.setBrightness(double) 0.0 1.0 1.0 1.0
Paralle.add(Connection) 0.0 1.0 1.0 1.0
R.R(int, String) 0.0 1.0 1.0 1.0
S.S(int, String) 0.0 1.0 1.0 1.0
S.dy(double, double) 0.0 1.0 1.0 1.0
A.display() 1.0 1.0 1.0 2.0
B.display() 1.0 1.0 1.0 2.0
Connection.dy(double) 1.0 1.0 2.0 2.0
D.display() 1.0 1.0 1.0 2.0
F.add() 1.0 1.0 1.0 2.0
F.display() 1.0 1.0 1.0 2.0
F.dy(double, double) 1.0 1.0 1.0 2.0
F.sub() 1.0 1.0 1.0 2.0
H.dy(double, double) 1.0 1.0 1.0 2.0
H.setIsOpen() 1.0 1.0 1.0 2.0
H.setR() 1.0 1.0 1.0 2.0
K.dy(double, double) 1.0 1.0 1.0 2.0
K.setIsOpen() 1.0 1.0 1.0 2.0
L.display() 1.0 1.0 1.0 2.0
L.dy(double) 1.0 1.0 1.0 2.0
Main.tmName(String) 1.0 2.0 2.0 2.0
R.display() 1.0 1.0 1.0 2.0
B.dy(double, double) 2.0 1.0 1.0 3.0
Device.compareTo(Device) 2.0 2.0 2.0 2.0
H.display() 2.0 1.0 1.0 3.0
K.display() 2.0 1.0 1.0 3.0
Main.find(String, ArrayList) 3.0 3.0 2.0 3.0
Paralle.dy(double, double) 3.0 1.0 3.0 3.0
Paralle.isOpen() 3.0 1.0 2.0 3.0
R.dy(double, double) 3.0 1.0 2.0 3.0
S.lightCount() 3.0 1.0 3.0 3.0
D.dy(double, double) 5.0 1.0 1.0 5.0
Connection.allMClose() 6.0 1.0 3.0 4.0
Paralle.sumR() 6.0 1.0 3.0 5.0
A.dy(double, double) 8.0 1.0 1.0 9.0
Connection.connectionAll() 8.0 2.0 5.0 6.0
Connection.sumR() 8.0 1.0 5.0 5.0
Device.init(String) 10.0 1.0 11.0 11.0
S.display() 14.0 1.0 1.0 12.0
Connection.isAllClose() 18.0 7.0 10.0 14.0
Main.main(String[]) 87.0 17.0 31.0 33.0
Class OCavg OCmax WMC
A 3.0 6.0 9.0
B 2.0 3.0 6.0
Connection 3.5 10.0 28.0
D 2.3333333333333335 4.0 7.0
Device 2.2222222222222223 11.0 20.0
F 1.6666666666666667 2.0 10.0
H 1.625 3.0 13.0
K 1.8 3.0 9.0
L 1.4 2.0 7.0
Light 1.0 1.0 3.0
Main 11.666666666666666 30.0 35.0
Paralle 3.0 5.0 12.0
R 2.0 3.0 6.0
S 3.0 7.0 12.0
Total 177.0
Average 2.6417910447761193 6.428571428571429 12.642857142857142

家居强电电路模拟程序-4

新增需求

引入二极管和要求输出每个引脚的电压,还有并联电路里面可以包含并联电路,还有对于电路中出现短路情况的判断,以及出现超过电器的额定电流的情况。

设计

二极管

首先先创建一个二极管类继承电器类,为其新增数据域来判断二极管是否导通。

设计如下:

class P extends Device{
    boolean order;
    public P(boolean order,int id, String name) {
        super(id, name);
        if (order){
            r=0;
            this.order=true;
        }
        r=100000000;
        compare = 10;
    }

    @Override
    public double dy(double in,double I) {
        if (I>8) current=true;
        this.in=in;
        out=this.in;
        return 0;
    }

    public void display(){
        String s=order?"conduction":"cutoff";
        String io=" "+(int)in+"-"+(int)out;
        System.out.println("@P" + getId() + ":"+s+io+(!current?"":" exceeding current limit error"));
    }
}

并联电路包含并联电路

这只需在主函数里面做一点判断就可以,如下:

else if (s.startsWith("#M")) {
    //处理并联电路
    Paralle paralle = new Paralle();
    //根据正则表达式匹配的字符找到对应的串联电路
    String regex = "(T\\d+)";
    Pattern pa = Pattern.compile(regex);
    Matcher m = pa.matcher(s);
    while (m.find()) {
        Connection d = connections.get(m.group(1));
        if (d != null)
            paralle.add(d);
    }
    sp.put(tmName(s), paralle);
}

电路中出现短路的情况

这个很好判断,出现短路,那就是某条串联电路闭合1,但是该条线路总电阻为0,由此就可以判断是否发生断路情况。如下:

public void shortCur(){
    for (Device device : sd) {
        if (device instanceof Paralle){
            ArrayList<Connection>sp=((Paralle)device).para;
            for (Connection connection : sp) {
                if (connection.isAllClose()&&connection.sumR()==0){
                    isShort=true;
                    break;
                }
            }
        }
    }
}

超过电器的额定电压

这个很好处理,只要每个设备重写父类的方法就可以实现,拿到电路,然后和额定电流比较,就完成了判断。

相关报表及类图

Method CogC ev(G) iv(G) v(G)
A.A(int, String) 0.0 1.0 1.0 1.0
B.B(int, String) 0.0 1.0 1.0 1.0
Connection.Connection(String) 0.0 1.0 1.0 1.0
Connection.I(double) 0.0 1.0 1.0 1.0
Connection.add(Device) 0.0 1.0 1.0 1.0
Connection.setIsOpen() 0.0 1.0 1.0 1.0
D.D(int, String) 0.0 1.0 1.0 1.0
Device.Device() 0.0 1.0 1.0 1.0
Device.Device(int, String) 0.0 1.0 1.0 1.0
Device.display() 0.0 1.0 1.0 1.0
Device.dy(double, double) 0.0 1.0 1.0 1.0
Device.getId() 0.0 1.0 1.0 1.0
Device.getName() 0.0 1.0 1.0 1.0
Device.setName(String) 0.0 1.0 1.0 1.0
F.F(int, String) 0.0 1.0 1.0 1.0
F.getCount() 0.0 1.0 1.0 1.0
H.H(int, String) 0.0 1.0 1.0 1.0
H.getIsOpen() 0.0 1.0 1.0 1.0
H.setFirst(String) 0.0 1.0 1.0 1.0
H.setSecond(String) 0.0 1.0 1.0 1.0
K.K(int, String) 0.0 1.0 1.0 1.0
K.getIsOpen() 0.0 1.0 1.0 1.0
L.L(int, String) 0.0 1.0 1.0 1.0
L.getCount() 0.0 1.0 1.0 1.0
L.setCount(double) 0.0 1.0 1.0 1.0
Light.Light(int, String) 0.0 1.0 1.0 1.0
Light.getBrightness() 0.0 1.0 1.0 1.0
Light.setBrightness(double) 0.0 1.0 1.0 1.0
Paralle.add(Connection) 0.0 1.0 1.0 1.0
R.R(int, String) 0.0 1.0 1.0 1.0
S.S(int, String) 0.0 1.0 1.0 1.0
Test.main(String[]) 0.0 1.0 1.0 1.0
A.display() 1.0 1.0 1.0 2.0
B.display() 1.0 1.0 1.0 2.0
Connection.dy(double, double) 1.0 1.0 2.0 2.0
D.display() 1.0 1.0 1.0 2.0
F.add() 1.0 1.0 1.0 2.0
F.display() 1.0 1.0 1.0 2.0
F.dy(double, double) 1.0 1.0 1.0 2.0
F.sub() 1.0 1.0 1.0 2.0
H.dy(double, double) 1.0 1.0 1.0 2.0
H.setIsOpen() 1.0 1.0 1.0 2.0
H.setR() 1.0 1.0 1.0 2.0
K.dy(double, double) 1.0 1.0 1.0 2.0
K.setIsOpen() 1.0 1.0 1.0 2.0
L.display() 1.0 1.0 1.0 2.0
L.dy(double) 1.0 1.0 1.0 2.0
Main.tmName(String) 1.0 2.0 2.0 2.0
P.P(boolean, int, String) 1.0 1.0 1.0 2.0
P.dy(double, double) 1.0 1.0 1.0 2.0
R.display() 1.0 1.0 1.0 2.0
S.dy(double, double) 1.0 1.0 1.0 2.0
B.dy(double, double) 2.0 1.0 1.0 3.0
Device.compareTo(Device) 2.0 2.0 2.0 2.0
H.display() 2.0 1.0 1.0 3.0
K.display() 2.0 1.0 1.0 3.0
P.display() 2.0 1.0 1.0 3.0
Main.find(String, ArrayList) 3.0 3.0 2.0 3.0
Paralle.dy(double, double) 3.0 1.0 3.0 3.0
Paralle.isOpen() 3.0 1.0 2.0 3.0
R.dy(double, double) 3.0 1.0 2.0 3.0
S.lightCount() 3.0 1.0 3.0 3.0
D.dy(double, double) 5.0 1.0 1.0 5.0
Connection.allMClose() 6.0 1.0 3.0 4.0
Paralle.sumR() 6.0 1.0 3.0 5.0
A.dy(double, double) 8.0 1.0 1.0 9.0
Connection.connectionAll() 8.0 2.0 5.0 6.0
Connection.sumR() 9.0 1.0 5.0 6.0
Connection.shortCur() 11.0 5.0 5.0 6.0
Device.init(String) 11.0 1.0 12.0 12.0
S.display() 15.0 1.0 1.0 13.0
Connection.isAllClose() 22.0 7.0 10.0 16.0
Main.main(String[]) 100.0 18.0 33.0 37.0
Total 246.0 105.0 151.0 220.0
Average 3.3698630136986303 1.4383561643835616 2.0684931506849313 3.0136986301369864
Class OCavg OCmax WMC
A 3.0 6.0 9.0
B 2.0 3.0 6.0
Connection 3.7 12.0 37.0
D 2.3333333333333335 4.0 7.0
Device 2.3333333333333335 12.0 21.0
F 1.6666666666666667 2.0 10.0
H 1.625 3.0 13.0
K 1.8 3.0 9.0
L 1.4 2.0 7.0
Light 1.0 1.0 3.0
Main 13.0 34.0 39.0
P 2.3333333333333335 3.0 7.0
Paralle 3.0 5.0 12.0
R 2.0 3.0 6.0
S 3.5 8.0 14.0
Test 1.0 1.0 1.0
Total 201.0
Average 2.7534246575342465 6.375 12.5625

踩坑心得

1.在判断总的电路信息时,没有考虑到串联电路的多层包含

改进后:

public double dy(double in,double I) {
    double v=in;
    for (Device device : sd) {
        double x=device.dy(v,I);
        v-=x;
    }
    return 0;
}

每个设备都有dy方法,如果出现多层串联包含,那么会发生递归调用,可以实现预期效果。

2.对于输出信息没有按顺序来输出

改进后:

public int compareTo(Device o) {
    if (o.compare != this.compare)
        return this.compare - o.compare;
    else
        return this.getId() - o.getId();
}

即重写设备类的比较方法,然后调用sort方法进行排序

改进建议

1.对于数据的解析,可以使用正则表达式来处理,但全部放在主函数中处理,显得主函数过于臃肿,可以适当抽取成方法,在主函数调取方法来实现数据的解析。

2.对于对象的存储,要选择合适的集合,例如对于在上述程序中的设备集合,就可以将储存设备集合的ArrayList改为HashMap,这样可以方便后续的查找,就不用特意写一个方法来查找设备。

总结

通过这最后两次的pta作业,我开始对软件工程问题从简单到复杂变换的过程有了一定的认识。通过pta的练习,我感受到了自己的能力有待提高,在今后的学习中,我要去慢慢提升自己的能力。

posted @ 2024-06-27 14:41  ylzq  阅读(20)  评论(0)    收藏  举报