一、前言
本次Blog为第七~八次大作业的总结。两次大作业主要考察抽象类及继承方面的相关内容,是在第六次大作业基础上的进一步升级,难度大幅提升,由于前面的作业我没有很好地完成,这两次大作业也没有拿到好成绩,这也算是提醒我:在进行一个设计时要提前为后续更加预留空间。
第七次大作业共一道题,即家居强电电路模拟程序-3,主要考察对继承和类的设计与使用,题目工作量大,在第二次家居强电电路模拟程序的基础上加入了两个电器:受控窗帘和互斥开关,其中互斥开关的处理是主要难点,因为一个互斥开关的节点会出现在两条支路上,所以在处理上要注意区分接入的端点,难度较大。
第八次大作业共一道题,即家居强电电路模拟程序-4,主要考察对继承和类的设计与使用,题目工作量大,在第三次家居强电电路模拟程序的基础上加入了一个电器:二极管,本题既要考虑二极管特性,又要加入每个电器管脚电压的显示,还需要考虑每个电器的最大限定电流,难度上大大提升,而且用于我之前的设计没有好好地考虑电流这一属性,所以在更改代码上显得更为困难,最终没能很好地完成这次pta。
二、设计与分析
1、 第七次大作业
第七次大作业添加了受控窗帘和互斥开关,受控窗帘需要在处理完电灯,得到环境光强后才能进行进一步操作,所以在处理时,我们要计算环境光强,在设置窗帘状态,进行互斥开关处理时,由于互斥开关可能同时控制两个支路,所以要把它当作两个同名电器处理,这也进一步加大了难度,在整体设计上,我设计了17个类:主类、设备总类、电路类、受控设备类、控制设备类、串联电路类、并联电路类、干路类、开关类、分档调速器类、连续调速器类、白炽灯类、日光灯类、吊扇类、落地扇类、互斥开关类、受控窗帘类。
概要设计:
设备总类(Electric):具备一些基本的设备属性,如设备名、电阻、电势差等,使用的方法有属性的set和get方法以及一个有参构造方法。
电路类(Circuit):继承自设备总类,自己有三个抽象方法,分别用于获取电路中的设备、判断该电路开闭状态、处理发送过来的命令,具体实现,在子类中完成。
受控设备类(Controlled):继承自设备总类,自己有一个抽象方法,用于打印设备信息。
控制设备类(Control):继承自设备总类,自己有两个抽象方法,分别用于打印设备信息、判断设备开关状态。
串联电路类(Serials):继承自电路类,有一个设备类型的列表,用于存储电路上的设备(包括电路上的电路类设备),共有四个方法分别用于传回设备列表、计算总电阻、处理受控设备状态、加入新的电器。
并联电路类(Parallel):继承自电路类,有一个串联电路类型的列表,存储电路上的各个支路,共有四个方法分别用于传回设备列表、计算总电阻、处理受控设备状态、加入新的串联电路;
干路类(Composite):继承自串联电路类,有两个方法用于处理收到的命令、展示电路状态。
开关类(Switch):继承自控制设备类,有一个属性显示开关开闭状态,有切换开关状态的方法。
分档调速器类(Binning):继承自控制设备类,本身包含挡数状态、记录各挡位输出电压数组两个属性及获取方法,以及一个获取输出电压的方法,两个调整挡位升降的方法,
连续调速器类(Continuous):继承自控制设备类,本身包含挡数状态一个属性,以及一个获取输出电压的方法,一个设置挡位的函数,还有一个打印当前状态的方法。
互斥开关类(Mutexswitch):继承自控制设备类,本身包含编号、状态两个属性,不同的状态代表不同的引脚接通,有一个可以切换状态的方法,一个可以返回电阻的方法。
白炽灯类(Incandescent):继承自受控设备类,本身包含光照强度一个属性,一个返回电阻的方法以及一个获取输出光强的方法,还有一个打印当前状态的方法printfdata。
日光灯类(Fluorescent):继承自受控设备类,本身包含光照强度一个属性,一个返回电阻的方法以及一个获取输出光强的方法,还有一个打印当前状态的方法printfdata。
吊扇类(Floorfan):继承自受控设备类,本身包含风扇转速一个属性,一个返回电阻的方法以及一个获取输出转速的方法,还有一个打印当前状态的方法。
落地扇类(Ceilingfan):继承自受控设备类,本身包含风扇转速一个属性,一个返回电阻的方法以及一个获取输出转速的方法,还有一个打印当前状态的方法。
受控窗帘类(Curtain):继承自受控设备类,本身包含打开比例、环境总光强两个属性,一个返回电阻的方法以及一个获取打开比例的方法,还有一个打印当前状态的方法。
主类(Main):初始化类的变量,有两个自己的方法,分别用于对输入信息进行处理、将数据输入复合电路类进行集中处理。
类图:
SourceMontor报表如图:
详细设计
1、设备总类
具备一些基本的设备属性,如设备名、电阻、电势差等,使用的方法有属性的set和get方法以及一个有参构造方法,它的主要职责是作为一个总父类,提供一个基础的模板,后续子类都在它的基础上具体实现。
2、电路类
继承自设备总类,自己有三个抽象方法,分别用于获取电路中的设备、判断该电路开闭状态、处理发送过来的命令,具体实现,在子类中完成,它的主要职责是作为一个电路父类,提供一个基础的模板,后续子类都在它的基础上具体实现。
3、受控设备类
继承自设备总类,自己有一个抽象方法,用于打印设备信息,它的主要职责是作为一个受控设备父类,提供一个基础的模板,后续子类都在它的基础上具体实现。
4、控制设备类
继承自设备总类,自己有两个抽象方法,分别用于打印设备信息、判断设备开关状态,它的主要职责是作为一个控制设备父类,提供一个基础的模板,后续子类都在它的基础上具体实现。
5、串联电路类
继承自电路类,有一个设备类型的列表,用于存储电路上的设备(包括电路上的电路类设备),共有四个方法分别用于传回设备列表、计算总电阻、处理受控设备状态、加入新的电器,它的主要职责是存储一个串联电路,并实现对串联电路的处理。为了让它可以处理传输回来的命令,我根据命令的不同进行不同的处理,同时考虑到串联电路中可能有其它电路,我会继续将命令交给其中的电路进行处理,以互斥开关为例,由于互斥开关的不同引脚存在于不同电路上,我们在处理输入的切换命令时会找到所有同名电器进行切换。同时我们加入判断该段电路是否闭合的方法,用于在最后处理时,方便判断该条电路是否会使干路为断路。
处理传入命令的一部分如图:
命令完成后处理设备状态的方法如图:
6、并联电路类
继承自电路类,有一个串联电路类型的列表,存储电路上的各个支路,共有四个方法分别用于传回设备列表、计算总电阻、处理受控设备状态、加入新的串联电路。它的主要职责是存储一个并联电路,并实现对并联电路的处理。使用的方法与串联电路类似,只在具体实现上有不同,比如命令处理函数时遍历使用支路,执行支路的处理命令函数。计算电阻时考虑某支路电阻为0或断路的情况。
计算电阻如图:
处理命令如图:
7、干路类
继承自串联电路类,有两个方法用于处理收到的命令、展示电路状态。使用的方法与串联电路基本相似,加入了展示电路状态的部分,所以使用treemap类型的属性,存储所有的控制设备、受控设备,并按序输出,这里利用了treemap自动排序的特性。
8、开关类
继承自控制设备类,有一个属性显示开关开闭状态,有切换开关状态的方法。
9、分档调速器类
继承自控制设备类,本身包含挡数状态、记录各挡位输出电压数组两个属性及获取方法,以及一个获取输出电压的方法,两个调整挡位升降的方法,
10、连续调速器类
继承自控制设备类,本身包含挡数状态一个属性,以及一个获取输出电压的方法,一个设置挡位的函数,还有一个打印当前状态的方法。
11、互斥开关类
继承自控制设备类,本身包含编号、状态两个属性,不同的状态代表不同的引脚接通,有一个可以切换状态的方法,一个可以返回电阻的方法。我将一个互斥开关分为两个设备,以引脚为2还是为3进行区分,并根据引脚和状态两个属性判断此处设备是否接通。代码如图:
12、白炽灯类
继承自受控设备类,本身包含光照强度一个属性,一个返回电阻的方法以及一个获取输出光强的方法,还有一个打印当前状态的方法。
13、日光灯类
继承自受控设备类,本身包含光照强度一个属性,一个返回电阻的方法以及一个获取输出光强的方法,还有一个打印当前状态的方法。
14、吊扇类
继承自受控设备类,本身包含风扇转速一个属性,一个返回电阻的方法以及一个获取输出转速的方法,还有一个打印当前状态的方法。
15、落地扇类
继承自受控设备类,本身包含风扇转速一个属性,一个返回电阻的方法以及一个获取输出转速的方法,还有一个打印当前状态的方法。
16、受控窗帘类
继承自受控设备类,本身包含打开比例、环境总光强两个属性,一个返回电阻的方法以及一个获取打开比例的方法,还有一个打印当前状态的方法。打开比例不仅与输入电压有关,与环境光强也有关,两个都需要考虑
17、主类
初始化类的变量,有两个自己的方法,分别用于对输入信息进行处理、将数据输入复合电路类进行集中处理。
2、 第八次大作业
第八次大作业在第七次大作业基础上引入了电流、管脚电压两个属性,要求对这两个属性进行输出,而且给每个电器加入最大电流的限制,同时引入设备二极管,二极管具有正向导通,反向截止的特性,这些都给这次pta加大了难度,由于我前几次都是采用根据电阻分电压的方式写的,所以对于要处理电流的情况,不出意外又要大改,但是这几周任务重,所以这次pta没有下大功夫,最终完成情况不佳。与上题类似,我设计了18个类:主类、设备总类、电路类、受控设备类、控制设备类、串联电路类、并联电路类、干路类、开关类、分档调速器类、连续调速器类、白炽灯类、日光灯类、吊扇类、落地扇类、互斥开关类、受控窗帘类、二级管类。其它方法没有大的变动,只是加入了输入电压、输出电压的计算,但是我没有处理好在并联电路中断开的开关两端的电压展示。
概要设计:
设备总类(Electric):具备一些基本的设备属性,如设备名、电阻、电势差、电流、输入电压、输出电压等,使用的方法有属性的set和get方法以及一个有参构造方法,还有一个负责判定是否超过最大电流的方法。
电路类(Circuit):继承自设备总类,自己有三个抽象方法,分别用于获取电路中的设备、判断该电路开闭状态、处理发送过来的命令,具体实现,在子类中完成。
受控设备类(Controlled):继承自设备总类,自己有一个抽象方法,用于打印设备信息。
控制设备类(Control):继承自设备总类,自己有两个抽象方法,分别用于打印设备信息、判断设备开关状态。
串联电路类(Serials):继承自电路类,有一个设备类型的列表,用于存储电路上的设备(包括电路上的电路类设备),共有四个方法分别用于传回设备列表、计算总电阻、处理受控设备状态、加入新的电器。
并联电路类(Parallel):继承自电路类,有一个串联电路类型的列表,存储电路上的各个支路,共有四个方法分别用于传回设备列表、计算总电阻、处理受控设备状态、加入新的串联电路;
干路类(Composite):继承自串联电路类,有两个方法用于处理收到的命令、展示电路状态。
开关类(Switch):继承自控制设备类,有一个属性显示开关开闭状态,有切换开关状态的方法。
分档调速器类(Binning):继承自控制设备类,本身包含挡数状态、记录各挡位输出电压数组两个属性及获取方法,以及一个获取输出电压的方法,两个调整挡位升降的方法,
连续调速器类(Continuous):继承自控制设备类,本身包含挡数状态一个属性,以及一个获取输出电压的方法,一个设置挡位的函数,还有一个打印当前状态的方法。
互斥开关类(Mutexswitch):继承自控制设备类,本身包含编号、状态两个属性,不同的状态代表不同的引脚接通,有一个可以切换状态的方法,一个可以返回电阻的方法。
白炽灯类(Incandescent):继承自受控设备类,本身包含光照强度一个属性,一个返回电阻的方法以及一个获取输出光强的方法,还有一个打印当前状态的方法printfdata。
日光灯类(Fluorescent):继承自受控设备类,本身包含光照强度一个属性,一个返回电阻的方法以及一个获取输出光强的方法,还有一个打印当前状态的方法printfdata。
吊扇类(Floorfan):继承自受控设备类,本身包含风扇转速一个属性,一个返回电阻的方法以及一个获取输出转速的方法,还有一个打印当前状态的方法。
二级管类:继承自受控设备类,本身包含输入节点和输出节点两个属性,有一个判断二级管正向反向的方法
落地扇类(Ceilingfan):继承自受控设备类,本身包含风扇转速一个属性,一个返回电阻的方法以及一个获取输出转速的方法,还有一个打印当前状态的方法。
受控窗帘类(Curtain):继承自受控设备类,本身包含打开比例、环境总光强两个属性,一个返回电阻的方法以及一个获取打开比例的方法,还有一个打印当前状态的方法。
主类(Main):初始化类的变量,有两个自己的方法,分别用于对输入信息进行处理、将数据输入复合电路类进行集中处理。
类图:
SourceMontor报表如图:
详细设计
1、设备总类
具备一些基本的设备属性,如设备名、电阻、电势差、电流、输入电压、输出电压等,使用的方法有属性的set和get方法以及一个有参构造方法,它的主要职责是作为一个总父类,提供一个基础的模板,后续子类都在它的基础上具体实现。
2、电路类
继承自设备总类,自己有三个抽象方法,分别用于获取电路中的设备、判断该电路开闭状态、处理发送过来的命令,具体实现,在子类中完成,它的主要职责是作为一个电路父类,提供一个基础的模板,后续子类都在它的基础上具体实现。电路类在处理时要求输入电流,根据电流完成输出电压的计算,在采用每个电器的输出电压为下一个电器的输入电压的方式进行处理,如图:
3、受控设备类
继承自设备总类,自己有一个抽象方法,用于打印设备信息,它的主要职责是作为一个受控设备父类,提供一个基础的模板,后续子类都在它的基础上具体实现。
4、控制设备类
继承自设备总类,自己有两个抽象方法,分别用于打印设备信息、判断设备开关状态,它的主要职责是作为一个控制设备父类,提供一个基础的模板,后续子类都在它的基础上具体实现。
5、串联电路类
继承自电路类,有一个设备类型的列表,用于存储电路上的设备(包括电路上的电路类设备),共有四个方法分别用于传回设备列表、计算总电阻、处理受控设备状态、加入新的电器,它的主要职责是存储一个串联电路,并实现对串联电路的处理。。
6、并联电路类
继承自电路类,有一个串联电路类型的列表,存储电路上的各个支路,共有四个方法分别用于传回设备列表、计算总电阻、处理受控设备状态、加入新的串联电路。它的主要职责是存储一个并联电路,并实现对并联电路的处理。
7、干路类
继承自电路类,有两个方法用于处理收到的命令、展示电路状态。使用的方法与串联电路基本相似,加入了展示电路状态的部分,所以使用treemap类型的属性,存储所有的控制设备、受控设备,并按序输出,这里利用了treemap自动排序的特性。
8、开关类
继承自控制设备类,有一个属性显示开关开闭状态,有切换开关状态的方法。
9、分档调速器类
继承自控制设备类,本身包含挡数状态、记录各挡位输出电压数组两个属性及获取方法,以及一个获取输出电压的方法,两个调整挡位升降的方法。
10、连续调速器类
继承自控制设备类,本身包含挡数状态一个属性,以及一个获取输出电压的方法,一个设置挡位的函数,还有一个打印当前状态的方法。
11、互斥开关类
继承自控制设备类,本身包含编号、状态两个属性,不同的状态代表不同的引脚接通,有一个可以切换状态的方法,一个可以返回电阻的方法。我将一个互斥开关分为两个设备,以引脚为2还是为3进行区分,并根据引脚和状态两个属性判断此处设备是否接通。代码如图:
12、白炽灯类
继承自受控设备类,本身包含光照强度一个属性,一个返回电阻的方法以及一个获取输出光强的方法,还有一个打印当前状态的方法。
13、日光灯类
继承自受控设备类,本身包含光照强度一个属性,一个返回电阻的方法以及一个获取输出光强的方法,还有一个打印当前状态的方法。
14、吊扇类
继承自受控设备类,本身包含风扇转速一个属性,一个返回电阻的方法以及一个获取输出转速的方法,还有一个打印当前状态的方法。
15、落地扇类
继承自受控设备类,本身包含风扇转速一个属性,一个返回电阻的方法以及一个获取输出转速的方法,还有一个打印当前状态的方法。
16、二级管类
继承自受控设备类,本身包含输入节点和输出节点两个属性,有一个判断二级管正向反向的方法
17、受控窗帘类
继承自受控设备类,本身包含打开比例、环境总光强两个属性,一个返回电阻的方法以及一个获取打开比例的方法,还有一个打印当前状态的方法。打开比例不仅与输入电压有关,与环境光强也有关,两个都需要考虑。
18、主类
初始化类的变量,有两个自己的方法,分别用于对输入信息进行处理、将数据输入复合电路类进行集中处理。
三、采坑心得
1、 第七次大作业
前两次大作业,在使用正则表达式时,我匹配”[]“的第二个编号创建设备,但是本次大作业,区分互斥开关的编号2、3可能在第一个也可能在第二个,我开始没处理好匹配,导致创建串联电路时,总会多出一个空设备,使得我在进行输入命令处理时会出现对不上的情况,命令无法正常处理。对于输入“#T1:[IN H1-1] [H1-2 D2-1] [D2-2 OUT]”,debug后内部如图:
之所以会这样,是因为我是采用一次创建一条电路的方式进行的,原本正则表达式的匹配会在[H1-2 D2-1]出停下,但是现在我要进行到[D2-2 OUT],在创建设备的函数里没有考虑输入为“OUT”的情况,而所以会返回一个NULL,但是我仍把它加入到电路中,一条电路就多了一个NULL设备,在处理输入命令时就会对开始被进行处理,就会出现以下错误:
所以后续我修改了逻辑,避免NULL设备的产生。
2、第八次大作业
第八次大作业要考虑电流影响,如果想要解决好,我们要从一开始,就根据u=IR的原则,分配电压,才能更好地处理,但是我没有做到,所以没有彻底完成代码地完善。
四、改进建议
1、首先还是代码编写注释问题,我这次虽然有了一些注释,但是在某些具体逻辑方面注释不足,导致重新编码变得困难,为了便于理解,还是应该添加详细注释。
2、这次我使用了大量抽象类,发现使用起来可以更好地将任务交给各个类负责,同时我发现接口是一种很好的拓展功能的方法,但是我没有使用接口,以后碰到这种编程,可以多使用接口解决问题。
3、设计框架时一定要充分考虑以后可能会碰到的问题,留足修改空间,才能应对复杂的变化。
4、设计时要符合Java、编程的那些原则,我没做考虑,所以在改进代码时就碰到了很多麻烦。
五、总结
这两次大作业大致经过上延续了之前三大作业的考核展示,即正则表达式和继承等相关知识的应用,我还设计了几个抽象类,这让我对抽象类有了更多了解。
第七次大作业,我在第六次大作业的基础上进行了大改,设计了四个抽象类作为父类,对于实现单一职责原则有很大帮助,一定程度上降低了编码难度,同时我发现如果采用接口,可能可以实现更好的结构。
第八次大作业,大致延续了第七次大作业的整体设计,但是没有很好完成本次pta,最好还是使用接口,方便简化结构降低编码难度。
这两次大作业我收获不少,主要是提高了我对抽象类的理解和使用能力,本学期对java的学习告一段落,今后,我也会继续学习,努力提升自己。
六、学期总结
本学期本门课程的学习到此结束了,从一开始接触java的陌生到第一次写pta大作业时的摸索,再到第一次遇到难题时的苦恼,直到现在我在这里敲下这段文字时的平静,我已经从最开始的java编程小白,变成了java学习路上的一名探索者,可以熟练地使用一些java中的方法,完成一些类的设计,这其中付出了许多汗水和努力。
这一学期的学习历程,教会了我:要学会主动拓展,才能更好解决问题。第四次大作业,我第一次进行结构上的大改,我大量使用Map这一数据结构,边学习边完成作业,那一次大作业竟然完成得还不错,如果继续使用List,我那次大作业会做得非常艰难。第二次大改是第七次大作业,我使用我并不熟悉的抽象类,进行了又一次大改,虽然最终没有顺利完成这次大作业,但是,很明显,抽象类可以帮助我做好职责划分,它的加入是一种更优解。java拥有丰富的数据结构和packet,如果发现现有的知识不足以解决问题,可以尝试进行拓展。
对于本门课程的学习,我最大的经验就是多请教、多交流,总有人会解决你没解决的问题,可以向他人请教,对解决自己的难题有很大帮助。同时,对基础的数据结构和编程原则的学习一定要扎实,扎实的基础可以帮助你更好地解决问题。
总的来说,本学期对Java的学习,不仅让我学习了编程知识,从中,我也学到了学习一门新编程语言的方法,收获颇丰。