一、前言
- 答题判题程序-4
- 新增内容:选择题,填空题,输出顺序的变化,考虑多个同学有多张不同试卷的答卷的情况
- 新增知识点:抽象类的运用;
- 在设计好前三次的题目集的情况下,将原本的题目类设计为抽象类(本来在第一次题目集的时候就可以如此设计,但是当时学的不够多),同时将输入的信息进行判断是否存在输入错误,考虑对正则表达式的合理重新设计,虽然违背了开闭原则,但是也是实属无奈。在经历了前三次的猛烈打击之后,我对设计原则的运用仍然不够熟练,迫使我不得不做出违反其规则的决定,在此,我对传道授业的老师表示抱歉......但是我也是在尽心尽力的完成任务了,虽然结果不怎么理想,但是我觉得过程也是值得回味的
- 家居强电电路模拟程序-1
- 考查内容:类的设计(由于cai老师给出了类的设计,所以说设计并不是很难),正则表达式的应用,对java中集合框架的熟悉与应用(例如:ArrayList),高中物理......
- 由于前几次的答题判题程序放弃的人越来越多,心善的cai老师为我们花费心思重新编写了一个题目以此来引导我们攻略PTA的题目,在此对cai老师表示由衷的感谢。但是由于我的高中物理不是很好,还没写之前就对本次题目集充满了恐惧,所幸cai老师一开始并没有把题目设计得十分复杂,在我经历了长达6小时的奋斗,终于是拿到了分数,但是由于我在审题时不够仔细(老毛病)导致我最终还是没能拿下满分。
- 家居强电电路模拟程序-2
- 新增内容:电阻,串联和并联,新的用电器(由于担心我们做不下去,cai老师便只更新了一点点内容)
- 在新增了一点点内容的前提下,对于我来说仍然是个巨大的挑战,由于我自身的时间分配出现问题,导致我没有用足够的时间来对新增内容进行分析导致我没有拿到一个期望的分数,并且由于我的在家居强电电路模拟程序-1正则表达式在家居强电电路模拟程序-2并不能完美适用,甚至于有些样例根本没办法用,我不得不重新设计我的正则表达式,并且由于我的第一次没拿到满分的原因被我找到,我重新整理了在Main方法中的程序设计以此方便进行输出和迭代。
二、设计与分析:
- 答题判题程序-4
- 类图分析:
- 从这张类图中不难看出我其实只完成了对正则表达式的分析和实现,甚至并没有对Question和Answer类进行抽象,此外实现了对数据的存储并使用集合框架HashMap对其进行了存储,因为我当时对抽象和继承的理解感觉并不是十分深刻,导致了我对本次PTA可谓是举步维艰,并且在当时感觉PTA真的不是给我这种人做的,我成了老师口中的“鸵鸟”,遇到困难就选择了退缩,而不是奋发向前,因此我选择在此对我的思路进行补充说明,以来弥补当时对此次PTA选择漠视的过错;
- 1.对于Question和Answer类应该写为一个抽象类,并让其对应的选择题,填空题对其进行继承,答案也是对应题目有一种答案方式继承于Answer;
- 2.对于正则表达式进行修订,对于每一个输入都有对应的正则表达式进行匹配,此外还要对其输入进行输入信息的判断,判断其输入是否为一个正确的输入;
- 3.对于已经输入并且正确的信息进行存储,按照正则表达式的解析对其进行对应的操作;
- 上面这些文字看起来十分简单,但是在真正实现时却十分困难,你还要对存储的数据考虑使用何种集合框架,以及如何合理的将不同的类联系起来,对其内容的解析如何拼接起来,这才是最考验人的地方,希望我以后一次为诫,做一个面对困难迎难而上的人。
- 家居强电电路模拟程序-1
- 类图分析:
- 首先,我们考虑到由于在日常电路中存在串联和并联以及他们俩的各种混合,一开始我是打算将串联和并联分开进行设计,但是这样子设计会导致如果窜并混联就会使得串联与并联电路之间无法联系起来,所以,我根据老师的设计建议让串联和并联都继承了有一个共同的父类Circuit方便将其联系起来;
- 其次,在电路中总的来说一共就俩种设备,一种时控制设备(例如:开关),另一种时被控制的设备(例如:电灯),因此就需要创建俩个Circuit的子类但是又是控制设备和被控设备的父类,以此来避免代码的高度复用,同时考虑对其抽象(虽然我没有对其进行抽象化......),并在最高层的类Circuit类中写出print方法,方便后续对方法进行重写和利用其进行信息的输出。
- 另外,考虑到对输入信息的匹配过于复杂,专门设计一个Matcher类来对字符串进行匹配,里面的属性主要是ArrayList
inputs;ArrayList circuitArrayList = new ArrayList<>();一个用来储存输入的信息,另一个则是对分析处理后的信息进行存储,同时在Matcher类中写入public void buildCircuit(){(略)};方法,完成对电路设备的写入以及分析结果的存储。 - 最后在Matcher类中的public void buildCircuit(){(略)};方法中写入对每一个信息进行输出即可。
- 家居强电电路模拟程序-2
- 类图分析:
- 由于在上一次题目集中看掉了这句话(按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇的顺序依次输出所有设备的状态或参数。),同时理解错了这句话(每个设备一行,同类设备按编号顺序从小到大输出)我不知道为什么我把每个设备一行理解成了每种设备一行......然后由于没注意到(按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇的顺序依次输出所有设备的状态或参数。)这句话,在第一次设计中,我并没有考虑到对每个类型都进行设计一个集合,导致我的最后那一点点分始终拿不到,附上图:
- 这是第一次中我主方法的写法:(单纯因为看掉了那句话,当时我无意间瞥见室友这么写还在想为什么,这样子传参数好麻烦,搞半天我是小丑......)
- 这是第二次看到了那句话之后主方法的写法:
- 由于在这次PTA中要开始考虑被控设备的电阻问题,所以个顶层父类Device新增了一个属性protected double resistance;在实例化对象对象的时候根据不同的设备初始化为不同的值,例如白炽灯的电阻为10,如下图:
- 其中this.setResistance(10);便是对白炽灯电阻的初始化。
- 此外,由于输出信息:同类设备按编号顺序从小到大输出,在上一次中我是在Matcher类中实现的排序,违背了单一职责的原则,这次我将其单独写成了一个Sort类,其中包含
ArrayList<K> kArrayList = new ArrayList<>();
ArrayList<F> fArrayList = new ArrayList<>();
ArrayList<L> lArrayList = new ArrayList<>();
ArrayList<B> bArrayList = new ArrayList<>();
ArrayList<R> rArrayList = new ArrayList<>();
ArrayList<D> dArrayList = new ArrayList<>();
ArrayList<A> aArrayList = new ArrayList<>(); 这些属性,方便我对其包含的被控设备进行分析和排序。其中的sort方法如图所示:
其实这样写就是在写重复代码,合理的设计来说我应该专门写一个冒泡排序的算法,然后在利用这个方法对上述的每一个属性进行排序可以大大减少代码量以及for循环的使用,避免代码的冗杂, - 在上一个类中虽然考虑了对并联类的设计,但并没有真正的实现并联类,在这次PTA中由于迭代的需要,我必须加入并联类,但由于并联类中可能含有串联电路,所以我把最开始打算设计为protected ArrayList
deviceArrayList = new ArrayList<>();的属性改为了protected ArrayList deviceArrayList = new ArrayList<>();,这样使得我的并联电路中不仅可以包含受控设备,也可以包含串联电路,同时在并联电路中写入并联电路电阻的求法,串联电路同理增加计算串联电路电阻的方法。 - 同时,由于新增了电阻属性,需要对电压重新进行分析,因此便有了Analyse类专门对其中经过了电阻的计算后来对电压进行分析,由于总体上来说就是一个大的串联中包含了一个并联电路,并且在最大的电路中接入VCC的一定时控制设备,因此可以在此直接调节输出后的电,分析时首先在串联电路中第电压和电阻成正比进行计算后,接着考虑并联电路中电压相等,但是并联电路中又有小的串联电路,即又要对其进行思考分压问题。
- 此外,分析后分析并不需要考虑引脚的问题,因此我对正则表达式进行了改进,将原先对很多信息都进行确切的匹配改为了对其进行模糊匹配,即每次只匹配输入信息[]中的后面半截信息即可处理整个电路的信息,更改前如图所示:
更改后如图所示:
三、采坑心得:
- 答题判题程序-4
- 由于我的时间分配出现了问题,导致我未能及时完成这个题目集,我以后一定不会再犯这种错误了,呜呜呜
- 家居强电电路模拟程序-1
- 眼瞎,没看见一句话,导致了出现重复设备的地方我一开始并没有对其进行排序,造成了如此后果
- 我在Matcher类中增加了排序算法后
- 但是仍存在几个测试点拿不到分
- 在题目集关闭后,我与同学和交流中发现我又少注意了一些题目信息(按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇的顺序依次输出所有设备的状态或参数)这使得我在最开始对数据进行如何存储时的思考产生了极大的偏差,导致在输出时无法完成如上信息的合理输出,是得最后四个测试点一直过不了。呜呜呜......我以后一定要认真看题目了!!!
- 在最开始的时候以为所有电压数据应该为int类型,但由于发现在中途计算时有些数据跟测试点存在极小的偏差,直到看到这句话(为避免精度的误差,所有有可能出现小数的数值用double类型保存并计算),于是我急急忙忙便将所有跟计算有关的数据全部改成了double类型。
- 此外,最后几个测试点应该还烤炉又多个开关的情况,要所有开关闭合之后电路才能形成通路,但是我一开始在此次PTA中并没有考虑此情况,导致了许多测试点都过不了
(这其中出现的格式错误是因为有的输出忘了换行,哈哈.......)
于是我在Matcher类中进行了如下修改
以此来判断是否所有的开关都关上了,如果没有的话就将整个电路的电压设置为0,改后如图:
- 家居强电电路模拟程序-2
- 由于出现了并联和串联的标识符,得对正则表达式进行大改,但在改进后发现group组会捕获不到所需的对象,即出现非零返回,后面发现时捕获组的设置出现了偏差,将其修正即可......
- 最开始对电路的理解不透彻,以为所有都得拆开分析,后面发现并联电路和串联电路俩可以一整个在一起分析,思路更改前:
思路更改后:
抽象的是,我不知道为什么改了之后连样例都过不去了,呜呜呜....... - 更加令人匪夷所思的是,明明我的串联电路的总电阻没有问题,但是每次计算之后的并联电阻和就为0,在调试过程中也出现了并联总电阻为Infinity且在我所有的数据均为double的情况下,一个人悄悄地碎了......
四、改进建议:
- 答题判题程序-4
- 合理的规划时间,正确在上一次的基础上进行迭代,考虑清楚如何在不违反开闭原则的基础上完成对其迭代的合理设计。
- 家居强电电路模拟程序-1
- Matcher类中的if判断多得超乎我的想象,并且代码相似度极高,造成了整体的冗杂以及严重违背单一职责原则,可以将此处封装在一个专门的分析类里面的方法,只需要对其传参调用即可,这样既解决了开闭原则,又完美的符合了单一职责原则,并且在后续的迭代中也只需要创建子类去继承其父类对其分析即可,大大增加了代码的迭代性。
- 此处的作用是对其开关进行判断,也可以将其单独拿出来做一个类来解耦,避免代码的耦合性过高,并且为每一条通路可以设置一个boolean属性的变量专门来判断这条路是否是一个通路。
- print函数嵌套在了一个巨大的循环里面,可以将其单独设计成一个Print类,利于实现单一职责和解耦,并且使代码的逻辑性更清晰,同时也实现了开闭原则。
- 家居强电电路模拟程序-2
- 在Analyse中实现了分析并联的方法,实际上可以将这个类进行抽象化,并且将分析功能写入继承它的子类当中,实现方法的重写,降低代码的耦合性,同时避免了强制类型转换会出现的各种错误,这样还可以少去for循环的多重嵌套。
- 计算电压可以单独做成一个计算类,将这个方法写入其中,到时候利用泛型进行传参即可,这样做也是为了单一职责的原则以及开闭原则和降低代码的耦合性。
- 此处的print利用了多次循环,实际上可以将其做成一个方法之后,只需要传入参数调用就好了,避免了代码的高度重复。
五、总结
- 1.学到了什么
- 其实cai老师为了我们也是操碎了心,又重新编写一个题目,PTA说白了其实就是要我们利用课堂上的知识来对题目进行分析后给出合理的设计,但是我也不知道为什么,写的时候根本就想不到那么多了,其实每次写PTA基本上没怎么用到面向对象的设计模式,在此对我的授课duan老师说一声抱歉。在PTA中我更最多的使学到了面向对象的原则的重要性,例如:单一职则原则,如果不能实现单一职责的原则,你会发现代码写到最后思路越写越乱,类与类之间的耦合性极高,可能可以跑得懂,但一定是令人头大的代码;开闭原则和依赖倒转实际上也是PTA所让我们所熟悉的俩大原则,因为PTA的作业都需要进行迭代,导致你如果不在第一次写的时候就考虑后面的事情,就会令自己在后面的迭代中寸步难行,充分体现了面向对象的思想在PTA中的应用。
- 2.我该做什么
- 实际上,我对duan老师所讲述的面向对象的设计模式十分感兴趣,上课的时候听的十分认真,但下课了就不愿意接着钻研课上的PPT,我知道这是一种很不好的习惯,我会在接下来的日子里行动起来。然后就是感觉很难做到真正意义上的知行合一,即我在课上的学习的知识很难在课后作业中运用起来,就算是duan老师上课讲其它例子我也感觉我很难运用,就是感觉脑子里面很多东西,但是我不知道到底该用哪一个去解决问题,不知道是不是自己对duan老师所讲的知识没有深度理解的原因,但不得不说,duan老师讲课的水平是一流的,但是感觉duan老师个人不是怎么喜欢讲课,我表示理解,毕竟没人会喜欢上班,谁不想躺着挣钱呢,haha
- 3.做出怎样的改变
- 不知不觉大一就快过去了,对于面向对象这门课感觉可能就学会了(bushi)duan老师上课所讲述的面向对象的设计模式,并且还是在自己并不能灵活运用的情况下,呜呜呜...另外就是脑子里满是面向对象的七大原则,但是经常说在嘴边的就是什么单一职责,开闭原则,迪米特法则这几个,说实话,跟面向对象的设计模式一样,即使脑子里有这些东西,感觉在运用的时候也不清楚到底用上没有,单一职责有时候实现了,有时候又会忘记。说到底,还是缺少练习,我应该做一个什么样的人,我自己都有,但是难以走出自己的舒适圈,我应该做出改变了!!!