OOP第三次博客总结
一、前言:总结三次题目集的知识点、题量、难度等情况
题目集七有两题,题目集八有一题,题目集九也只有一题。题目集七的难度不大,虽然题目集八的题目量不多,但是难度较大,每题都要写将近四天。这三次的题目集包含的知识点较多。题目集7需要我们掌握类的继承、多态性使用方法以及接口的应用;题目集8和题目集9只有一道题目,但难度很大,重点考核类设计中的封装性(关联、依赖、聚集三种),需要我们理清各个类之中的关系,类之间一对多的,多对一。最后两次的题目难度大,这也对我们的所掌握的知识的综合考察。
题目集7知识点:
继承、多态的应用;ArrayList泛型的应用方法;Comparable接口及泛型的应用;单一职责原则的应用;“开-闭”原则的应用。
题目集8,9知识点:
类的合理设计;ArrayList泛型的应用方法;抽象类的应用方法;继承与多态的应用。
二、设计与分析
①题目集7(7-1)、(7-2)两道题目的递进式设计分析总结
7-1
这一题目集考察我们掌握类的继承、多态性使用方法以及接口的应用。题目为图形卡片排序游戏,,卡片分为 四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid),并给出各种 卡片的相应参数,要求学生能够迅速求出各卡片的面积大小然后将卡片按照其面积值从大到小进行排 序,同时求出所有卡片的面积之和。
题目指导书给出了主方法源码:
public class Main {
//在Main类中定义一个静态Scanner对象,这样在其它类中如果想要使用该对象进行输入,则直接
//使用Main.input.next…即可(避免采坑)
public static Scanner input = new Scanner(System.in);
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<Integer>();
int num = input.nextInt();
while(num != 0){
if(num < 0 || num > 4){
System.out.println("Wrong Format");
System.exit(0);
}
list.add(num);
num = input.nextInt();
}
DealCardList dealCardList = new DealCardList(list);
if(!dealCardList.validate()){
System.out.println("Wrong Format");
System.exit(0);
}
dealCardList.showResult();
input.close();
}
}

先创建一个抽象类Shape类,抽象类中包含几个抽象方法,
public abstract double getArea();
public abstract boolean validate();
创建Circle类,Rectangle类,Trapezoid类,Triangle类去继承Shape类,重写抽象方法,不同的类,计算面积的公式不同,判断是否输入错误不同。
创建Card类
class Card implements Comparable<Card>{
Shape shape;
Card(){
}
Card(Shape shape){
this.shape=shape;
}
public Shape getShape() {
return shape;
}
public void setShape(Shape Shape) {
this.shape=shape;
}
@Override
public int compareTo(Card card) {
// TODO Auto-generated method stub
return (int)(shape.getArea()-card.getShape().getArea());
}
}
使用Comparable接口,此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
使用compare To方法对各个类的对象的面积进行排序
7-2
这是7-1的沿袭题目
本次作业主要对卡片(Card)进行分组游戏,其规则为随机发放一些卡片给学生, 卡片仍然分为四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid), 并给出各种卡片的相应参数,要求学生首先根据卡片类型将所有卡片进行分组(一个类型分为一组, 所以最多四组),然后能够对每组内的卡片根据面积值从大到小进行排序,同时求出该组内所有卡片 的面积之和,最后求出每组卡片面积之和中的最大值。

相较于7-1,7-2在很大程度上只是修改了数据的输出,我创建了一个数组用来存储面积,后面使用它进行数据的比较和计算。
double sum1[]=new double[a];double sum2[]=new double[b];double sum3[]=new double[c];double sum4[]=new double[d];
double num1=0;double num2=0;double num3=0;double num4=0;
int i=0;int j=0;int k=0;int l=0;
for(Card card : cardList) {if(card.getShape().getShapeName()=="Circle") {sum1[i]=card.getShape().getArea();i++;num1=num1+card.shape.getArea();}}
for(Card card : cardList) {if(card.getShape().getShapeName()=="Rectangle") {sum2[j]=card.getShape().getArea();j++;num2=num2+card.shape.getArea();} }
for(Card card : cardList) {if(card.getShape().getShapeName()=="Triangle") {sum3[k]=card.getShape().getArea();k++;num3=num3+card.shape.getArea();} }
for(Card card : cardList) {if(card.getShape().getShapeName()=="Trapezoid") {sum4[l]=card.getShape().getArea();l++;num4=num4+card.shape.getArea();}}
System.out.println("The Separated List:");System.out.print("[");
for(i=0;i<sum1.length;i++) {System.out.print("Circle:"+String.format("%.2f", sum1[i])+" ");}
System.out.print("]");System.out.print("[");
for(i=0;i<sum2.length;i++) {System.out.print("Rectangle:"+String.format("%.2f", sum2[i])+" ");}
System.out.print("]");System.out.print("[");
for(i=0;i<sum3.length;i++) {System.out.print("Triangle:"+String.format("%.2f", sum3[i])+" ");}
System.out.print("]");System.out.print("[");
for(i=0;i<sum4.length;i++) {System.out.print("Trapezoid:"+String.format("%.2f", sum4[i])+" ");}
System.out.println("]");System.out.println("The Separated sorted List:");
for(int m=0;m<sum1.length;m++){for(int n=0;n<sum1.length-1-m;n++)
{if(sum1[n]<sum1[n+1])
{double temp=sum1[n];sum1[n]=sum1[n+1];sum1[n+1]=temp;}}}
for(int m=0;m<sum2.length;m++){for(int n=0;n<sum2.length-1-m;n++)
{ if(sum2[n]<sum2[n+1])
{double temp=sum2[n];sum2[n]=sum2[n+1];sum2[n+1]=temp;}}}
for(int m=0;m<sum3.length;m++)
{for(int n=0;n<sum3.length-1-m;n++)
{if(sum3[n]<sum3[n+1])
{double temp=sum3[n];sum3[n]=sum3[n+1];sum3[n+1]=temp;}}}
for(int m=0;m<sum4.length;m++)
{for(int n=0;n<sum4.length-1-m;n++)
{if(sum4[n]<sum4[n+1])
{double temp=sum4[n];sum4[n]=sum4[n+1];sum4[n+1]=temp;}}}
System.out.print("[");
for(i=0;i<sum1.length;i++) {System.out.print("Circle:"+String.format("%.2f", sum1[i])+" ");}
System.out.print("]");System.out.print("[");
for(i=0;i<sum2.length;i++) {System.out.print("Rectangle:"+String.format("%.2f", sum2[i])+" ");}
System.out.print("]");System.out.print("[");
for(i=0;i<sum3.length;i++) {System.out.print("Triangle:"+String.format("%.2f", sum3[i])+" ");}
System.out.print("]");System.out.print("[");
for(i=0;i<sum4.length;i++) {System.out.print("Trapezoid:"+String.format("%.2f", sum4[i])+" ");}
System.out.println("]");
double sumnum[]=new double[4];
sumnum[0]=num1; sumnum[1]=num2; sumnum[2]=num3; sumnum[3]=num4;
for(int m=0;m<sumnum.length;m++)
{for(int n=0;n<sumnum.length-1-m;n++)
{if(sumnum[n]<sumnum[n+1])
{double temp=sumnum[n];sumnum[n]=sumnum[n+1];sumnum[n+1]=temp;}}}
System.out.println("The max area:"+String.format("%.2f",sumnum[0]));}}
这个代码过于冗长,垃圾代码(emmm)。还超过长度限制了。
②题目集8和题目集9两道ATM机仿真题目的设计思路分析总结
题目集8:

设计思路分析:根据业务说明,先构建六个实体类,ChinaUnionPay类、Bank类、User类、Account类、Card类、ATM类,每个类中都有不同的属性,
Bank类:
private String bankNO;
private String bankName;
private ArrayList<Account> accountList = new ArrayList<Account>();
private ArrayList<ATM> ATMList = new ArrayList<ATM>();
User 类:
private String ID;
private String name;
private String Phone;
ArrayList<Account> list = new ArrayList<Account>();
Account 类:
private String accountNO;
private double balance = 0;
private User user = null;
private Bank bank = null;
private static ArrayList<Card> list = new ArrayList<Card>();
Card 类:
private String cardNO;
private String cardPassword;
private Account account = null;
ATM 类:
private String ATMID;
private Bank bank = null;
将各个类联系起来:
private ArrayList<Account> accountList = new ArrayList<Account>();
private ArrayList<ATM> ATMList = new ArrayList<ATM>();
ArrayList<Account> list = new ArrayList<Account>();
private static ArrayList<Card> list = new ArrayList<Card>();
用Array List将他们联系起来,一个用户有多个账号,一个账号下有多张卡,银联中有多个银行,银行中有多个ATM机,一系列一对多大关系。
数据的存储:
public void addAccount(Account account) {
this.list.add(account);
}
public void removeAccount(Account account) {
this.list.remove(account);
}
ccb.addAccount(ccbAcc1);
ccb.addAccount(ccbAcc2);
ccb.addAccount(ccbAcc3);
icbc.addAccount(icbcAcc1);
icbc.addAccount(icbcAcc2);
icbc.addAccount(icbcAcc3);
icbc.addAccount(icbcAcc4);
icbc.addAccount(icbcAcc5);
用迭代器访问,寻找各个账户,用户,卡
Iterator<Bank> bankItr = unionPay.getBankList().iterator();
Bank bank = null;
ATM aTM = null;
while(bankItr.hasNext()) {
bank = bankItr.next();
Iterator<ATM> aTMItr = bank.getATMList().iterator();
while(aTMItr.hasNext()) {
aTM = aTMItr.next();
if(aTM.getATMID().equals(ATMID)) {
return aTM;
剩下的算法很简单,就不需要拿出来介绍了。
题目集9:
题目集9是在题目集8的基础上的沿袭题目,它增加了一个新的功能要求,增加了借记卡。银行账户分为借记账户和贷记账户两种,其中,借记账户不能够透支 取款,而贷记账户可以透支取款,这里需要支付手续费。我们将Account类改成抽象类,写DebtAccount类,CreditAccount类继承Account类。

贷款额度为50000,在检查余额时要判断最终的金额是否小于-50000。检查金额时情况比较复杂,首先要判断为哪种卡,如果是贷记卡,然后就要判断它当前余额是大于0还是小于0,因为大于0的部分与小于0的部分税率不同,再然后就是判断跨行的情况,税率又有区别,这个余额是减去税率后金额满足条件才行,不是光余额大于取的钱。如果你的检查金额情况过了的话,之后的考虑就按照这个分类讨论就好。
存款取款操作也是按照之前检查金额的顺序来,先是判断账户种类,若为贷记卡,则要分取款的金额是否大于余额,再分是否跨行,再在之前的嵌套里分余额是否大于0,取款的金额小于余额较简单,然后是借记卡的话会简单的多,讨论的情况少很多。
三、踩坑心得
1.题目集7-1,在对面积排序时,错误的将它们从小到大排序,而题目要求的是将他们从大到小排序
2.题目集8,在存入数据时,数据太多,卡号和账号太长,输入时输入错误,导致无法通过测试点,让我误以为是我的算法错误,耽误了很多的时间。
3.题目集9,计算利率时,将利息的小数点打错
4.题目集9,在对账户余额进行更改时,传参错误,导致里面的数据根本没有变动
5.题目集9,算法错误。
最初算法:
if(account.getAccounttype().equals("Credit")) { if (account.getBank().getBankNO() != aTM.getBank().getBankNO()) { if(aTM.getBank().getBankNO().equals("1001")) { m=amount+Math.abs(amount)*0.02; } if(aTM.getBank().getBankNO().equals("1002")) { m=amount+Math.abs(amount)*0.03; } if(aTM.getBank().getBankNO().equals("1003")) { m=amount+Math.abs(amount)*0.04; } } if(amount>balance&&balance>0) { n=(amount-balance)*0.05; } if(amount>balance&&balance<=0) { n=amount*(0.05+1); } if(balance-m-n<-50000.00) { System.out.print("Sorry,your account balance is insufficient."); System.exit(0); }else { account.setBalance(balance-m-n); } }
修改后:
m=0; n=amount; if(account.getAccounttype().equals("Credit")) { if (account.getBank().getBankNO() != aTM.getBank().getBankNO()) { if(aTM.getBank().getBankNO().equals("1001")) { m=Math.abs(amount)*0.02; } if(aTM.getBank().getBankNO().equals("1002")) { m=Math.abs(amount)*0.03; } if(aTM.getBank().getBankNO().equals("1003")) { m=Math.abs(amount)*0.04; } } if(amount>account.getBalance()&&account.getBalance()>0) { n=(amount-balance)*1.05+balance; } if(amount>account.getBalance()&&account.getBalance()<=0) { n=amount*1.05; } if(balance-m-n<-50000.00) { System.out.println("Sorry,your account balance is insufficient."); System.exit(0); }else { account.setBalance(balance-m-n); } }
我花费了好长时间将这个利息算明白。
四、改进意见
1.对于较难的题目,比如题目集8,希望老师能多给点提示,很多东西自己很难能够想到,思考就花费了很长时间
2.题目集7-2,我的代码太冗长,一些用来for循环的地方可以将它改成ArrayList,在对面积排序时,可以将冒泡排序法改成Compare To方法,更加简洁
3.对于题目集8,希望能多给些测试点,我数据存储错误让我误以为是我的算法出错了,耽误了好多时间。
五、总结
1.编程的单一职责原则可以很清楚地看到各个类之间的关系即结构,对于方法的复写,我们要充分了解,处理每个类之间的关系。
2.再次练习了类的定义、方法的调用、参数的传递、对象的构造与使用,类的封装,Array List的使用。
3.子类继承父类,重写父类的抽象方法
4.代码还是需要每天多写,中间两天偷懒了一会儿,再次摸电脑时,打字速度都变慢了。

浙公网安备 33010602011771号