OO第七,八次大作业总结
一、前言
在这个学期即将迎来尾声的时候,这个阶段的大作业也迎来了最后的两个迭代大作业,而本次博客就将围绕这两个迭代大作业讲述
二、设计与分析
这两次的迭代作业的类设计其实没有很多的变化,只不过根据题目要求添加了互斥开关和受控窗帘,二极管这几个类,其中互斥开关是控制器的子类,受控窗帘属于设备的子类,二极管属于仪器类的子类。
因为受控窗帘的窗帘开放程度的参数是根据整个系统的光照强度设置的,所以我写了一个方法在整个电路都运行了之后再根据电路中所有的灯的亮度对这个窗帘的开放程度进行调整。
而针对互斥开关的内部细节操作,我则是设置了一个变量port,用来表示该互斥开关开关搭在哪一个引脚上,当port为2时,电流传进引脚二,当port为3时,电流传进引脚三,port为一时,则传进引脚一,这也是针对当引脚二和引脚三都在引脚一前面的情况。而二极管则是当引脚二在前的时候,该二极管反接,电阻无限大。
下面两张图分别是前一次博客和这一次博客时SourceMonitor的分析报告
从图片上可以看出来,在两次的代码的文件数量增多了4个,因为除开了上面讲到的三个类之外,还有一个窗帘的抽象类,作为受控窗帘的父类。
而在代码行数上,从688行到984行,多了大约三百行的样子,主要是第八次大作业的修改多了一些,在引脚的接入方向从以前除了互斥开关可能会存在引脚1在同元件后,变成了所有元件的引脚1与引脚2的顺序都可能随机,这点会在踩坑心得中详谈。并且在输出信息方面,多加了输出元件所有的引脚的信息这一点,这点也使我修改了不少,虽然在我之前写的代码当中是会将电压通过传参的方式传递经过所有的元件,但是在最后这一次大作业上却没能做到完成该题所有的要求,仍然存在一些错误。
而在注释占比上也相较于上一次有一点提升,从8.4到9.2说明我也已经慢慢养成了在写代码时为代码注释的习惯了,不过这方面还仍需要提高。
而最大的函数深度由5变成了6,这说明我的最多的分支嵌套语句变多了,这并不是一个很好的消息,分支嵌套语句越多,则方法的复杂度也会上升,代码的出错率也会上升,同时代码的可读性的和可修改性都会变得更加地难,而我应该降低方法的深度。
而这张图是整个代码的分析结果,从上面可以看到CircuitMember类的代码行数占比是第二高的,该类作为所有元件类的父类,其中包含的参数变量和方法数量是很多的,从图中就可以看到该类中包含了24个方法。
而代码行数最多的则是LinkCenter类,作为链接所有电子元件的类,其承担了十分重要的责任,在我写的代码运行模式下,所有的电路元件的运行都只需要从整个电路的电源处输入电压就可以了,而后面的元件的运行则会通过互相调用各自的运行方法并且传递电压参数而运行,如下面这个串代码
@Override
public void Input(double input){
setInput(input);
Run();
Output(getOutput());
}
setInput方法是通过传递的电压参数而对该类中的输入电压参数进行修改,而Run方法则是每个设备自己的运行方法,这个方法在Device类中设为了抽象方法,因为每种设备有自己的运行规则,所以设为抽象方法要求所有的设备子类都要实现这个方法而OutPut方法则是将输出电压传递给下一个引脚,而所有的引脚也会有个传递电压的方法。 而其中的getOutput方法则是返回变量参数中的输出电压的值,而输出电压的值则是在setInput方法内就会设置好的,我把设置输出电压的写在setInput方法内也是考虑到,当有了输入电压之后就应该会同时拥有输出电压,如果在这个setInput方法下面再写一个setOutput方法感觉会不太合适,我认为输入电压和输出电压两个变量就相当于两个绑定的属性就和JavaFX中的绑定属性这一个特性一样,所以我认为在设置了输入电压后就应该不用同时在setInput方法后面跟上一个setOutput方法。
而我的输出电压则就只是通过输入电压减去设备使用的电压差。而这个电压差则是当设备获得电流的时候也会同步设置的,即电流乘以电阻得到电压差。而电流的计算则是通过串流电路内的运行方法了,即下面这个代码块
@Override
public void Input(double input){//重写Input方法,输入电压到该电路后,由电路对线路进行处理
setInput(input);
checkConnection();
calculateResistance();
SpeedController speedController = containsSpeedController();
if( speedController!= null) {
speedController.setVoltage(voltage);
voltage = speedController.getVoltage();
}
electricity = circuitConnected ? (voltage !=0 ? voltage / resistance : 0) : 0;
for(CircuitMember member : line) {
member.setElectricity(electricity);//电路该电路中的元件设置电流
member.setCircuitConnected(circuitConnected);
}
firstPin.Input(getInput());
OUT.Input(getOutput());
}
先是设置输入电压,然后checkConnection方法检测电路是否连通,是否出现了断路的情况.而calculateResistance方法统计电路中的总电阻,在这个方法内获取每个元件的电阻我都是通过了调用getResistance方法,因为调用这个方法可以直接获取所有元件的电阻,而不需要额外写代码面对不同的情况,比如电阻计算不太一样的并联电路,而我只要在并联电路的类中重写getResistance方法就可以根据该电路自身电阻的特殊性计算电阻了,这样更符合单一职责这个原则,并联电路的电阻的计算就是并联电路自身的职责了。而这样的好处就是我不需要在串联电路的calculateResistance方法中额外写出几个if-else语句用来额外处理并联电路这个电阻计算比较与众不同的怪胎了,同时还能避免增加这个方法的复杂度。
而containsSpeedController这个方法则是判断该电路中是否存在调速控制器的如果存在则返回该调速器(调速器类是这一类调速器的父类),否则返回null。如果存在则该电路的电压差发生改变,不过只有干路存在调速器,这方法主要针对作为干路的串联电路有作用。
而下面则是计算电流的值了,circuitConnected是一个表示电路是否连通的布尔类型的变量,当电路连通时才计算电流值,否则电流值为0,而为了避免当电压差为0导致算出的值为NaN这种值的情况我又在其中添加了电压差不为0的条件,否则电流值也为0,可以看到我在这里使用了三元运算符的方法给电流变量赋值,这么写主要是感觉比起使用if-else语句,这样写更加清晰明了,而且也缩短了代码的行数,如果就为了给一个电流值的变量赋值我还要写一个两层嵌套的语句,而且那样写不如这样的简洁。
而下面这个循环语句就是对所有的电路内的成员设置电流值,在setElectricity方法内也会同步修改电压差参数的值
最下面两行则是从电路中的第一个元件的引脚输入电压和向该串联电路后的元件引脚输入电压了。
三、踩坑心得
在最后一次大作业中因为同一个元件的引脚的先后顺序可以不同,比如引脚2可以出现在引脚1的前面,这点对于我写的代码的影响还是偏大的,因为最初我在设计类的时候担心可能之后会有元件的两个引脚不会以1或2的编号命名,或者同一条电路中的引脚顺序不会按照连接的顺序输入,这会对连接电路的那个方法造成一定的影响,所以我就在引脚类中添加了一个布尔类型的参数isInputPort,用于表示该引脚是不是输入端的引脚并且在创建这些引脚的时候就对这些引脚的inputPort参数进行了设置,但这一次的大作业中这一种输入模式打破了我原本的写的模式,所以我不得不对原有代码进行比较多的修改,并且在这一次的大作业中我删除了isInpuPort这一个参数,毕竟这一次输入模式的较大改变,我也不得不对这种设计进行修改。这也让我明白在给类添加参数之前应该要先思考该参数是否合理,是否符合应用。
在前几次大作业中,因为我给引脚类添加的inputPort这个参数,所以我在第三次大作业添加了互斥开关时为了应对出现引脚1在引脚2,3后的情况,我还写了一个方法用于对这种情况下的三个引脚的isInputPort这个参数进行修改,但在这一次大作业之后我就反思,在写第三次大作业的时候也许我就应该删除掉这个参数了,这也是我的疏忽点。
四、总结
在这一阶段的大作业中,我对于Java中的继承和多态的使用更加熟练了,继承和多态的使用使得整个代码更加具有灵活性,并且这提高了代码的重用性,当我使用继承的时候就可以避免写过多相同的方法,并且多态的使用也提高了我代码的简洁性,就比如我这个代码中的CircuitMember类作为电路元件的父类,在使用链表的时候范型我可以直接写成LinkedList<CircuitMember>,这样就可以储存所有的电子元件对象了,而不用为所有的类的对象都新建一个新的链表,并且这样的形式,我也不用额外写一个排序方法了,只需要为CircuitMember类实现Comparable接口的compareTo方法就可以了。
但是虽然继承和多态虽然好用,但是并非什么情况都可以用,还是得根据实际情况使用,并且在使用继承的时候父类的设计就要更加的谨慎了,因为其子类越多,修改父类的一处地方法后,有时就会涉及到很多类的修改,这样对于修改程序是一个灾难,所以继承虽然优点多,但也不能无脑使用,还是得在满足了“是一种的”的条件后使用才是对的。
在类的参数变量的添加上应该要思考该参数的存在是否合理,是否符合要求,是否不会造成代码的效率变差。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步