面向对象第一单元总结

  第一单元的主要目标是了解面向对象的概念、认识对象的关键特性、了解并逐渐掌握层次化抽象和设计方法。单元内三次作业都围绕着函数求导这一主题,循序渐进地培养编写基本的面向对象程序的能力。

一、第一次作业:幂函数求导

  第一次作业的要求是对仅包含常数和幂函数的多项式进行求导。自然的想法是,构造一个“项”对象,它包含系数和指数两个变量,多项式便是这样的项的集合。读入一个项后检查是否能与现有项合并化简,之后依次按公式求导,输出时优先输出系数为正的项。比较复杂的部分是输入环节,由于规则繁多,我总结出一个状态机并据此实现了InputReader类:

  度量分析:

    方法:

InputReader.InputReader()1.01.01.0
InputReader.isNumber(char)1.01.02.0
InputReader.isSign(char)1.01.02.0
InputReader.isSpace(char)1.01.02.0
InputReader.phase0(ArrayList)5.06.08.0
InputReader.phase1(ArrayList)5.05.08.0
InputReader.phase2(ArrayList)3.07.08.0
InputReader.phase3(ArrayList)2.03.05.0
InputReader.phase4(ArrayList)3.05.06.0
InputReader.phase5(ArrayList)4.04.06.0
InputReader.phase6(ArrayList)3.02.04.0
InputReader.phase7(ArrayList)2.06.07.0
InputReader.phase8(ArrayList)2.02.07.0
InputReader.readItems(ArrayList)5.06.07.0
Item.add(Item)1.01.01.0
Item.calcNewCoeff()1.01.01.0
Item.derive(boolean)1.09.09.0
Item.getCoefficient()1.01.01.0
Item.getIndex()1.01.01.0
Item.getNewCoefficient()1.01.01.0
Item.isAlive()1.01.01.0
Item.Item(String,String)1.01.01.0
PolynomialDerivation.combineItems()1.011.011.0
PolynomialDerivation.main(String[])6.06.07.0

    类:

InputReader4.056.0
Item1.87515.0
PolynomialDerivation7.014.0
Total 85.0
Average3.541666666666666528.333333333333332

    UML类图:

    这次作业由于要求简单,实现的结构也较为简单,不需要继承、接口等。主要可优化的部分在于InputReader类,最好改成更加可读的实现方式。

  BUG:

    主要BUG来源于对输入数据规范的理解不清晰。例如在何种情况下允许正负号与系数之间出现空格,对空行和无输入的处理等。在编写过程中发现BUG的主要方法是根据自己认为的边界值及易错点构建测试样例,与同学交换测试样例大量测试。

 

二、第二次作业:三角函数以及函数相乘

  第二次作业的规则引入了sin(x)和cos(x)函数,并且允许一项内出现同类或异类函数相乘。我第一次作业的设计不能表示这样的结构,需要在项(Item)之下引入新的因子(Factor)类。将InputReader中的部分状态机删除并简化为readFunction()、readItem()等函数。读入sin(x)和cos(x)时利用规则投机取巧采用了字符串间隔匹配,导致第三次作业该部分需要重写。有考虑到基于sin(x)^2+cos(x)^2=1的优化,但实现过程中出现了bug,最终舍弃。

  度量分析:

    方法:

Factor.add(Factor)1.01.01.0
Factor.derive()3.02.06.0
Factor.Factor(String,String)2.02.05.0
Factor.getIndex()1.01.01.0
Factor.getType()1.01.01.0
Factor.getValue()1.01.01.0
Factor.isConst()1.02.02.0
Factor.isNegativeOne()1.02.02.0
Factor.isOne()2.02.02.0
Factor.isPositive()1.01.01.0
Factor.isZero()1.02.02.0
Factor.setIndex(BigInteger)1.01.01.0
Factor.sub(Factor)1.01.01.0
Factor.times(Factor)1.02.02.0
Factor.toString()4.04.04.0
InputReader.filterSpaces()1.02.03.0
InputReader.InputReader()1.01.01.0
InputReader.intervalMatching(String)3.03.04.0
InputReader.isFunction(char)1.01.03.0
InputReader.isNumber(char)1.01.02.0
InputReader.isSign(char)1.01.02.0
InputReader.isSpace(char)1.01.02.0
InputReader.newItem(Polynomial)1.02.02.0
InputReader.phase0(Polynomial)4.06.06.0
InputReader.phase1(Polynomial)4.06.06.0
InputReader.phase2(Polynomial)3.04.04.0
InputReader.phase3(Polynomial)2.06.06.0
InputReader.phase4(Polynomial)4.05.05.0
InputReader.phase5(Polynomial)8.02.09.0
InputReader.readFunction(Polynomial,String)5.09.09.0
InputReader.readIndex()5.04.08.0
InputReader.readPolynomial(Polynomial)5.05.06.0
InputReader.seriesMatching(String)3.03.04.0
Item.add(Item)1.01.01.0
Item.combine(Item)2.02.03.0
Item.derive()2.06.07.0
Item.getFactors()1.01.01.0
Item.isPositive()1.01.01.0
Item.isSameType(Item)3.02.03.0
Item.isZero()1.01.01.0
Item.Item()1.01.01.0
Item.sub(Item)1.01.01.0
Item.times(Factor)1.01.01.0
Item.times(Item)1.02.02.0
Item.times(String)1.01.01.0
Item.toString()2.07.07.0
Polynomial.add(Item)3.05.05.0
Polynomial.add(Polynomial)1.02.02.0
Polynomial.combine()2.05.06.0
Polynomial.derive()1.02.02.0
Polynomial.getItems()1.01.01.0
Polynomial.isEmpty()1.01.01.0
Polynomial.Polynomial()1.01.01.0
Polynomial.toString()2.05.07.0
PolynomialDerivation.main(String[])1.02.02.0

    类:

Factor1.933333333333333329.0
InputReader3.38888888888888961.0
Item2.07692307692307727.0
Polynomial3.024.0
PolynomialDerivation2.02.0
Total 143.0
Average2.628.6

    UML类图:

    为方便合并同类项,对Factor以及Item类定义了基本运算,但其实add()与sub()是重复的。虽然没有继承自己定义的父类,但第一次重载了toString()方法,使得输出多项式更加简单,也更加便于输出前的检查。

  BUG:

    在实现cos(x)^2+sin(x)^2=1优化时出现了两个未能通过的中测数据点。后来经过分析,初步认定是化简后合并同类项时系数计算错误导致的。另一方面,加入因子类使得项的合并需要经过大量搜索,前期采用ArrayList存储因子会使得时间复杂度提升一个量级,因此改用HashMap实现。但这又是一个仅对第二次作业适用的手段(因为所有的sin和cos函数都相同)。

 

三、第三次作业:函数嵌套

  第三次作业不再限制函数的自变量为x,这意味着三角函数和幂函数可以不断递归嵌套。我采用的方法是将幂函数、三角函数的自变量定义为多项式(多项式为项的和,项为系数和函数的积),再定义一个没有因子的x函数作为递归结构的终点。与递归构建多项式对应,在读入数据是采用了完全可解释的递归读入方法。第三次作业由于输入复杂,优化算法时间复杂度高风险高而收益低,因此只做了合并同类项程度的优化。

  度量分析:

    方法:

ConstFunc.ConstFunc(String)1.01.01.0
ConstFunc.derive()1.01.01.0
ConstFunc.getIndex()1.01.01.0
ConstFunc.getType()1.01.01.0
ConstFunc.getVar()1.01.01.0
ConstFunc.isSameTypeWith(Func)1.01.01.0
ConstFunc.isSameWith(Func)1.02.02.0
ConstFunc.times(Func)1.01.01.0
CosFunc.CosFunc(Polynomial,String)1.01.01.0
CosFunc.derive()1.02.02.0
CosFunc.getIndex()1.01.01.0
CosFunc.getType()1.01.01.0
CosFunc.getVar()1.01.01.0
CosFunc.isSameTypeWith(Func)1.02.02.0
CosFunc.isSameWith(Func)1.02.02.0
CosFunc.times(Func)1.01.01.0
CosFunc.toString()2.03.03.0
InputReader.atEnd()1.02.02.0
InputReader.filterSpaces()1.02.03.0
InputReader.InputReader()1.02.02.0
InputReader.isNumber(char)1.01.02.0
InputReader.isSign(char)1.01.02.0
InputReader.isSpace(char)1.01.02.0
InputReader.newConstPoly(String)1.01.01.0
InputReader.newFuncPoly(Func)2.01.02.0
InputReader.readConstFunc()2.01.02.0
InputReader.readCosFunc()4.01.04.0
InputReader.readFunc()7.07.08.0
InputReader.readIndex()4.03.05.0
InputReader.readInSin()9.09.012.0
InputReader.readItem()5.08.011.0
InputReader.readPolynomial(Polynomial,boolean)7.03.09.0
InputReader.readPowerFunc()2.01.02.0
InputReader.readSignedInt()5.04.08.0
InputReader.readSinFunc()4.01.04.0
InputReader.readXFunc()2.01.02.0
InputReader.seriesMatching(String)3.03.04.0
Item.add(Item)1.01.01.0
Item.derive()2.04.05.0
Item.filterOne()1.03.03.0
Item.getCoefficient()1.01.01.0
Item.getFuncArray()1.01.01.0
Item.isOne()1.02.02.0
Item.isPositive()1.01.01.0
Item.isSameTypeWith(Item)6.03.06.0
Item.isSameWith(Item)1.02.02.0
Item.isZero()4.03.05.0
Item.Item()1.01.01.0
Item.processFunc(int)2.03.03.0
Item.times(Func)5.06.07.0
Item.times(Item)1.02.02.0
Item.times(String)1.01.01.0
Item.toString()1.06.07.0
Polynomial.add(Item)3.04.04.0
Polynomial.add(Polynomial)1.02.02.0
Polynomial.clone()1.02.02.0
Polynomial.derive()1.02.02.0
Polynomial.filterZero()1.03.03.0
Polynomial.getItems()1.01.01.0
Polynomial.isOne()1.02.02.0
Polynomial.isSameWith(Polynomial)6.03.06.0
Polynomial.isZero()4.02.04.0
Polynomial.multiFactor()1.03.03.0
Polynomial.multiItem()1.01.01.0
Polynomial.Polynomial()1.01.01.0
Polynomial.times(Item)1.02.02.0
Polynomial.times(Polynomial)1.02.02.0
Polynomial.toString()2.05.07.0
PolynomialDerivation.main(String[])1.02.02.0
PowerFunc.derive()1.02.02.0
PowerFunc.getIndex()1.01.01.0
PowerFunc.getType()1.01.01.0
PowerFunc.getVar()1.01.01.0
PowerFunc.isSameTypeWith(Func)1.02.02.0
PowerFunc.isSameWith(Func)1.02.02.0
PowerFunc.PowerFunc(Polynomial,String)1.01.01.0
PowerFunc.times(Func)1.01.01.0
PowerFunc.toString()1.02.02.0
SinFunc.derive()1.02.02.0
SinFunc.getIndex()1.01.01.0
SinFunc.getType()1.01.01.0
SinFunc.getVar()1.01.01.0
SinFunc.isSameTypeWith(Func)1.02.02.0
SinFunc.isSameWith(Func)1.02.02.0
SinFunc.SinFunc(Polynomial,String)1.01.01.0
SinFunc.times(Func)1.01.01.0
SinFunc.toString()2.03.03.0
XFunc.derive()1.02.02.0
XFunc.getIndex()1.01.01.0
XFunc.getType()1.01.01.0
XFunc.getVar()1.01.01.0
XFunc.isSameTypeWith(Func)1.01.01.0
XFunc.isSameWith(Func)1.02.02.0
XFunc.times(Func)1.01.01.0
XFunc.toString()2.02.02.0
XFunc.XFunc(String)1.01.01.0

    类:

 

ConstFunc1.08.0
CosFunc1.333333333333333312.0
InputReader3.570.0
Item2.562541.0
Polynomial2.53333333333333338.0
PolynomialDerivation2.02.0
PowerFunc1.222222222222222311.0
SinFunc1.333333333333333312.0
XFunc1.222222222222222311.0
Total 205.0
Average2.135416666666666522.77777777777778

    UML类图:

    定义了Func接口,由于前期对题目理解的问题,多定义了一个PowerFunc用于处理装载(x+2)^2的函数。由于实际不会出现,故其指数固定为1,用作多项式容器。常函数仅为便于读入而存在,因为对Item(项)类的定义中有单独的系数代表所有常数的乘积,而在读入时一并视为因子读入。这是设计得不够优美的地方。多项式类函数过多有些冗杂,其中有一些为优化而存在的函数最终并未调用。

  BUG:

    在输出时省略了部分括号导致出现BUG。比如cos(x+2)是非法输出,应为cos((x+2))。这与我在设计程序时将多项式直接作为三角函数的自变量不无关系,但可以通过在输出时添加一些判断解决。

 

四、Applying Creational Pattern

  对于存储多项式、项和函数的类,都定义了基本运算、求导和输出函数,因此可看做使用了工厂模式。在前两次作业中尝试了简单工厂模式,第三次作业部分使用了抽象工厂模式。简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个程序结构的优化。但在类的数量增多时,难以理清大局。这三次作业是不断重构的过程,已经可以体现一部分对创建模式的改进。若对第三次作业进一步改进,可以考虑的方向有:拆分InputReader,将Function的加、乘方法写进父类等。

转载于:https://www.cnblogs.com/starmind/p/10611187.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值