第三阶段Blog:题目集7~9
转眼间“面向对象程序设计”这门课程也来到了尾声。在这个学期的学习中,我从最早的如第一个Blog所讲的对输入输出都感到有点困惑,到逐渐掌握Java的语法并较为熟悉的应用,再到对面向对象的思想进一步加深和了解,这其中可谓收获颇丰。但依然还有许多内容需要我们进一步学习,进一步深入探索。如同最后几节课讲到的建造者模式、桥接模式等等,更让我感到面向对象思想的学习学无止境。我们还有很长的一段路要走。
一、前言
第七次作业
第七次作业的题目分别是:
7-1 图形卡片排序游戏
7-2 图形卡片分组游戏
运用知识点
本组题目集核心内容为通过对Comparable接口的继承以及compareTo方法的实现,利用父类列表ArrayList<Shape>,完成对不同子类图形的排序Collections.sort();,从而利用继承与多态完成批量化规范操作。
难度
7-1 ☆☆
7-2 ☆☆☆
第八次作业
第八次作业的题目分别是:
7-3 ATM机类结构设计(一)
运用知识点
本次作业核心在于对面向对象规范化设计的考察。在于总体设计上对类职责的分配与调用。
难度
7-3 ☆☆☆
第九次作业
第九次作业的题目分别是:
7-1 ATM机类结构设计(二)
运用知识点
本次题目集是上一次题目集的延续,继续考察面向对象总体规范化设计。
难度
7-1 ☆☆☆☆
二、设计与分析
1、题目集7(7-1)、(7-2)两道题目的递进式设计分析总结
题目集7(7-1)
类图

复杂度分析

源代码
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Scanner; public class Main { static ArrayList<Shape>duilist = new ArrayList<Shape>(); public static void main(String[] args) { Scanner scan = new Scanner(System.in); String astr = scan.nextLine(); String alist[] = astr.split("\\s+"); int len=0; if(check1(alist)) { for(int i = 0; i<alist.length ;i++) { if(alist[i].equals("0")) break; len++; if(alist[i].equals("1")) { Circle a = new Circle(); double r = scan.nextDouble(); a.settervalue(r); duilist.add(a); } else if(alist[i].equals("2")) { Rectangle a = new Rectangle(); double w = scan.nextDouble(); double l = scan.nextDouble(); a.settervalue(w, l); duilist.add(a); } else if(alist[i].equals("3")) { Triangle a = new Triangle(); double s1 = scan.nextDouble(); double s2 = scan.nextDouble(); double s3 = scan.nextDouble(); a.settervalue(s1, s2, s3); duilist.add(a); } else if(alist[i].equals("4")) { Trapezoid a = new Trapezoid(); double sh = scan.nextDouble(); double xia = scan.nextDouble(); double h = scan.nextDouble(); a.settervalue(sh, xia, h); duilist.add(a); } } for(int i=0; i<len; i++) { if(!judge(duilist.get(i))) { System.out.println("Wrong Format"); System.exit(0); } } for(int i=0; i<len; i++) { jisuan(duilist.get(i)); } System.out.println("The original list:"); for(int i=0; i<len; i++) { duilist.get(i).selfClass(); System.out.printf("%.2f ",duilist.get(i).getArea()); } System.out.printf("\nThe sorted list:\n"); Collections.sort(duilist); for(int i=len-1; i>=0; i--) { duilist.get(i).selfClass(); System.out.printf("%.2f ",duilist.get(i).getArea()); } double an = 0; for(int i=0; i<len; i++) { an += duilist.get(i).area; } System.out.printf("\nSum of area:%.2f\n",an); } else { System.out.println("Wrong Format"); } } public static boolean check1(String alist[]) { for(int i=0; i<alist.length; i++) { if( !alist[i].equals("1")&&!alist[i].equals("2")&&!alist[i].equals("3")&&!alist[i].equals("4")&&!alist[i].equals("0") ) return false; } return true; } static boolean judge(Shape o) { return o.validate(); } static void jisuan(Shape o) { o.suanArea(); } } class Shape implements Comparable<Shape>{ double area; double getArea() { return area; } boolean validate() { return false; } void suanArea() { } void selfClass() { } @Override public int compareTo(Shape object) { if(this.getArea() > object.getArea()){ return 1; } else if(this.getArea() < object.getArea() ){ return -1; } return 0; } } class Circle extends Shape{ double radius; void settervalue(double radius) { this.radius = radius; } @Override boolean validate() { if(radius>0) return true; return false; } @Override void suanArea() { area = Math.PI*radius*radius; } @Override void selfClass() { System.out.print("Circle:"); } } class Rectangle extends Shape{ double width; double length; void settervalue(double width, double length) { this.width = width; this.length = length; } @Override boolean validate() { if(width>=0 && length>=0) return true; return false; } @Override void suanArea() { area = width*length; } @Override void selfClass() { System.out.print("Rectangle:"); } } class Triangle extends Shape{ double side1; double side2; double side3; double bian[] = new double[3]; void settervalue(double side1, double side2, double side3) { this.side1 = side1; this.side2 = side2; this.side3 = side3; } @Override boolean validate() { if(side1>=0 && side2>=0 && side3>=0) { bian[0] = side1; bian[1] = side2; bian[2] = side3; Arrays.sort(bian); if(bian[0]+bian[1]>bian[2]) { return true; } } return false; } @Override void suanArea() { double p=(side1+side2+side3)/2; area = Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); } @Override void selfClass() { System.out.print("Triangle:"); } } class Trapezoid extends Shape{ double shdi; double xiadi; double h; void settervalue(double side1, double side2, double side3) { this.shdi = side1; this.xiadi = side2; this.h = side3; } @Override boolean validate() { if(shdi>=0 && xiadi>=0 && h>=0) { return true; } return false; } @Override void suanArea() { area = (shdi+xiadi)*h/2.0; } @Override void selfClass() { System.out.print("Trapezoid:"); } }
题目集7(7-2)
类图

复杂度分析

源代码
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Scanner; public class Main { static ArrayList<Shape>duilist = new ArrayList<Shape>(); static ArrayList<Circle>cs = new ArrayList<Circle>(); static ArrayList<Rectangle>rs = new ArrayList<Rectangle>(); static ArrayList<Triangle>ts = new ArrayList<Triangle>(); static ArrayList<Trapezoid>tzs = new ArrayList<Trapezoid>(); public static void main(String[] args) { Scanner scan = new Scanner(System.in); String astr = scan.nextLine(); String alist[] = astr.split("\\s+"); int len=0; if(check1(alist)) { for(int i = 0; i<alist.length ;i++) { if(alist[i].equals("0")) break; len++; if(alist[i].equals("1")) { Circle a = new Circle(); double r = scan.nextDouble(); a.settervalue(r); duilist.add(a); } else if(alist[i].equals("2")) { Rectangle a = new Rectangle(); double w = scan.nextDouble(); double l = scan.nextDouble(); a.settervalue(w, l); duilist.add(a); } else if(alist[i].equals("3")) { Triangle a = new Triangle(); double s1 = scan.nextDouble(); double s2 = scan.nextDouble(); double s3 = scan.nextDouble(); a.settervalue(s1, s2, s3); duilist.add(a); } else if(alist[i].equals("4")) { Trapezoid a = new Trapezoid(); double sh = scan.nextDouble(); double xia = scan.nextDouble(); double h = scan.nextDouble(); a.settervalue(sh, xia, h); duilist.add(a); } } for(int i=0; i<len; i++) { if(!judge(duilist.get(i))) { System.out.println("Wrong Format"); System.exit(0); } } for(int i=0; i<len; i++) { jisuan(duilist.get(i)); } originalList(); classification(); separatedList(); separatedSort(); separatedSortedList(); maxArea(); } else { System.out.println("Wrong Format"); } } public static boolean check1(String alist[]) { if(alist[0].equals("0")) return false; for(int i=0; i<alist.length; i++) { if( !alist[i].equals("1")&&!alist[i].equals("2")&&!alist[i].equals("3")&&!alist[i].equals("4")&&!alist[i].equals("0") ) return false; } return true; } static boolean judge(Shape o) { return o.validate(); } static void jisuan(Shape o) { o.suanArea(); } static void classification() { for(int i=0; i<duilist.size(); i++) { if(duilist.get(i).getClass()==Circle.class) cs.add( (Circle)duilist.get(i) ); else if(duilist.get(i).getClass()==Rectangle.class) rs.add( (Rectangle)duilist.get(i) ); else if(duilist.get(i).getClass()==Triangle.class) ts.add( (Triangle)duilist.get(i) ); else if(duilist.get(i).getClass()==Trapezoid.class) tzs.add( (Trapezoid)duilist.get(i) ); } } static void originalList() { System.out.println("The original list:"); System.out.print("["); for(int i=0; i<duilist.size(); i++) { duilist.get(i).selfClass(); System.out.printf("%.2f ",duilist.get(i).getArea()); } System.out.println("]"); } static void separatedList() { System.out.println("The Separated List:"); System.out.print("["); for(int i=0; i<cs.size(); i++) { cs.get(i).selfClass(); System.out.printf("%.2f ",cs.get(i).getArea()); } System.out.print("]"); System.out.print("["); for(int i=0; i<rs.size(); i++) { rs.get(i).selfClass(); System.out.printf("%.2f ",rs.get(i).getArea()); } System.out.print("]"); System.out.print("["); for(int i=0; i<ts.size(); i++) { ts.get(i).selfClass(); System.out.printf("%.2f ",ts.get(i).getArea()); } System.out.print("]"); System.out.print("["); for(int i=0; i<tzs.size(); i++) { tzs.get(i).selfClass(); System.out.printf("%.2f ",tzs.get(i).getArea()); } System.out.println("]"); } static void separatedSort() { Collections.sort(cs); Collections.sort(rs); Collections.sort(ts); Collections.sort(tzs); } static void separatedSortedList() { System.out.println("The Separated sorted List:"); System.out.print("["); for(int i=cs.size()-1; i>=0; i--) { cs.get(i).selfClass(); System.out.printf("%.2f ",cs.get(i).getArea()); } System.out.print("]"); System.out.print("["); for(int i=rs.size()-1; i>=0; i--) { rs.get(i).selfClass(); System.out.printf("%.2f ",rs.get(i).getArea()); } System.out.print("]"); System.out.print("["); for(int i=ts.size()-1; i>=0; i--) { ts.get(i).selfClass(); System.out.printf("%.2f ",ts.get(i).getArea()); } System.out.print("]"); System.out.print("["); for(int i=tzs.size()-1; i>=0; i--) { tzs.get(i).selfClass(); System.out.printf("%.2f ",tzs.get(i).getArea()); } System.out.println("]"); } static void maxArea() { double sumShape[] = new double[4]; for( int i=0; i<sumShape.length; i++ ) { sumShape[i]=0; } for( int i=0; i<cs.size(); i++ ) { sumShape[0]+=cs.get(i).getArea(); } for( int i=0; i<rs.size(); i++ ) { sumShape[1]+=rs.get(i).getArea(); } for( int i=0; i<ts.size(); i++ ) { sumShape[2]+=ts.get(i).getArea(); } for( int i=0; i<tzs.size(); i++ ) { sumShape[3]+=tzs.get(i).getArea(); } double aMaxSumArea=0; for( int i=0; i<sumShape.length; i++ ) { if(sumShape[i]>aMaxSumArea) aMaxSumArea=sumShape[i]; } System.out.printf("The max area:%.2f\n",aMaxSumArea); } } class Shape { double area; double getArea() { return area; } boolean validate() { return false; } void suanArea() { } void selfClass() { } } class Circle extends Shape implements Comparable<Circle>{ double radius; void settervalue(double radius) { this.radius = radius; } @Override boolean validate() { if(radius>0) return true; return false; } @Override void suanArea() { area = Math.PI*radius*radius; } @Override void selfClass() { System.out.print("Circle:"); } @Override public int compareTo(Circle object) { if(this.getArea() > object.getArea()){ return 1; } else if(this.getArea() < object.getArea() ){ return -1; } return 0; } } class Rectangle extends Shape implements Comparable<Rectangle>{ double width; double length; void settervalue(double width, double length) { this.width = width; this.length = length; } @Override boolean validate() { if(width>=0 && length>=0) return true; return false; } @Override void suanArea() { area = width*length; } @Override void selfClass() { System.out.print("Rectangle:"); } @Override public int compareTo(Rectangle object) { if(this.getArea() > object.getArea()){ return 1; } else if(this.getArea() < object.getArea() ){ return -1; } return 0; } } class Triangle extends Shape implements Comparable<Triangle>{ double side1; double side2; double side3; double bian[] = new double[3]; void settervalue(double side1, double side2, double side3) { this.side1 = side1; this.side2 = side2; this.side3 = side3; } @Override boolean validate() { if(side1>=0 && side2>=0 && side3>=0) { bian[0] = side1; bian[1] = side2; bian[2] = side3; Arrays.sort(bian); if(bian[0]+bian[1]>bian[2]) { return true; } } return false; } @Override void suanArea() { double p=(side1+side2+side3)/2; area = Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); } @Override void selfClass() { System.out.print("Triangle:"); } @Override public int compareTo(Triangle object) { if(this.getArea() > object.getArea()){ return 1; } else if(this.getArea() < object.getArea() ){ return -1; } return 0; } } class Trapezoid extends Shape implements Comparable<Trapezoid>{ double shdi; double xiadi; double h; void settervalue(double side1, double side2, double side3) { this.shdi = side1; this.xiadi = side2; this.h = side3; } @Override boolean validate() { if(shdi>=0 && xiadi>=0 && h>=0) { return true; } return false; } @Override void suanArea() { area = (shdi+xiadi)*h/2.0; } @Override void selfClass() { System.out.print("Trapezoid:"); } @Override public int compareTo(Trapezoid object) { if(this.getArea() > object.getArea()){ return 1; } else if(this.getArea() < object.getArea() ){ return -1; } return 0; } }
对二者的分析
事实上,两道题目的核心都在于通过对Comparable接口的继承以及compareTo方法的实现,利用父类列表ArrayList<Shape>,完成对不同子类图形的排序Collections.sort();,从而利用继承与多态完成批量化规范操作。并且二者都极大地利用了继承和多态实现批量化操作。区别在于第一道题只是利用父类完成对所有Shape的面积的一次排序和计算,而第二道题需要输出分组后的图形类型及面积,按照“Circle、Rectangle、Triangle、Trapezoid”的顺序依次输出。可以看到,如果仍然把子类放到一个列表中操作可以预见到复杂度将会大大提高。因此,在本次实验中,我通过创建其各个子类的列表,将其率先向下转型分好类别,然后再对各个列表操作。因此在很好利用多态批量化规范化操作的前提下又能非常合适的完成目标并极大的减少了工作量。题目二多出的向下转型十分关键。
2、题目集8和题目集9两道ATM机仿真题目的设计思路分析总结
题目集8
类图

复杂度分析

源代码
由于题目集9在题目集8基础上改进而来,因此只在下文放上题目集9的代码
题目集9
类图

复杂度分析

源代码
import java.util.ArrayList; import java.util.Scanner; public class Main { static ArrayList<Bank> bankList = new ArrayList<Bank>(); static ArrayList<Account> accountList = new ArrayList<Account>(); public static void main(String[] args) { initBank(); initAccount(); Scanner scan = new Scanner(System.in); String astr=new String(); while(!(astr=scan.nextLine()).equals("#")){ int accountno; int bankno; String[] alist=astr.split("\\s+");//输入的每行数据用空格隔开,存为数组 if( alist.length==1 ) { if( (accountno=seekAccount(alist[0])) == -1 ) { System.out.println("Sorry,this card does not exist."); continue; } System.out.printf("业务:查询余额 ¥%.2f\n",accountList.get(accountno).getterMoney()); } else if( alist.length==4 ) { if( (accountno=seekAccount(alist[0]))==-1 ) { System.out.println("Sorry,this card does not exist."); continue; } if( !checkPassword(accountno,alist[0],alist[1]) ) { System.out.println("Sorry,your password is wrong."); continue; } if( (bankno=checkATM( accountno, alist[2]))==-2 ) { System.out.println("Sorry,the ATM's id is wrong."); continue; } double amoney = Double.parseDouble(alist[3]); double kuahangmoney=needkuahangMoney(accountno,amoney,bankno); if(!operateMon(accountno,amoney,kuahangmoney)) { System.out.println("Sorry,your account balance is insufficient."); continue; } if(bankno==-1) System.out.printf("业务:取款 %s在%s的%s号ATM机上取款¥%.2f\n",accountList.get(accountno).getterMastername() ,accountList.get(accountno).getterBank().getterBankName() ,alist[2], amoney); else System.out.printf("业务:取款 %s在%s的%s号ATM机上取款¥%.2f\n",accountList.get(accountno).getterMastername() ,bankList.get(bankno).getterBankName() ,alist[2], amoney); System.out.printf("当前余额为¥%.2f\n",accountList.get(accountno).getterMoney()); } } } public static void initBank() { Bank zgjs = new Bank(); zgjs.setterName("中国建设银行"); zgjs.setterShouxufei(0.02); zgjs.setterATM("01"); zgjs.setterATM("02"); zgjs.setterATM("03"); zgjs.setterATM("04"); bankList.add(zgjs); Bank zggs = new Bank(); zggs.setterName("中国工商银行"); zggs.setterShouxufei(0.03); zggs.setterATM("05"); zggs.setterATM("06"); bankList.add(zggs); Bank zgny = new Bank(); zgny.setterName("中国农业银行"); zgny.setterShouxufei(0.04); zgny.setterATM("07"); zgny.setterATM("08"); zgny.setterATM("09"); zgny.setterATM("10"); zgny.setterATM("11"); bankList.add(zgny); } public static void initAccount() { accountList.add(new Account()); accountList.get(0).setterBank( bankList.get(0) ); accountList.get(0).setterAcc(1); accountList.get(0).setterMaster("杨过"); accountList.get(0).opMonry(-10000.00); accountList.get(0).settercard("6217000010041315709", "88888888"); accountList.get(0).settercard("6217000010041315715", "88888888"); accountList.add(new Account()); accountList.get(1).setterBank( bankList.get(0) ); accountList.get(1).setterAcc(1); accountList.get(1).setterMaster("杨过"); accountList.get(1).opMonry(-10000.00); accountList.get(1).settercard("6217000010041315718", "88888888"); accountList.add(new Account()); accountList.get(2).setterBank( bankList.get(0) ); accountList.get(2).setterAcc(1); accountList.get(2).setterMaster("郭靖"); accountList.get(2).opMonry(-10000.00); accountList.get(2).settercard("6217000010051320007", "88888888"); accountList.add(new Account()); accountList.get(3).setterBank( bankList.get(1) ); accountList.get(3).setterAcc(1); accountList.get(3).setterMaster("张无忌"); accountList.get(3).opMonry(-10000.00); accountList.get(3).settercard("6222081502001312389", "88888888"); accountList.add(new Account()); accountList.get(4).setterBank( bankList.get(1) ); //System.out.println(bankList.get(0).getterBankName()); accountList.get(4).setterAcc(1); accountList.get(4).setterMaster("张无忌"); accountList.get(4).opMonry(-10000.00); accountList.get(4).settercard("6222081502001312390", "88888888"); accountList.add(new Account()); accountList.get(5).setterBank( bankList.get(1) ); accountList.get(5).setterAcc(1); accountList.get(5).setterMaster("张无忌"); accountList.get(5).opMonry(-10000.00); accountList.get(5).settercard("6222081502001312399", "88888888"); accountList.get(5).settercard("6222081502001312400", "88888888"); accountList.add(new Account()); accountList.get(6).setterBank( bankList.get(1) ); accountList.get(6).setterAcc(1); accountList.get(6).setterMaster("韦小宝"); accountList.get(6).opMonry(-10000.00); accountList.get(6).settercard("6222081502051320785", "88888888"); accountList.add(new Account()); accountList.get(7).setterBank( bankList.get(1) ); accountList.get(7).setterAcc(1); accountList.get(7).setterMaster("韦小宝"); accountList.get(7).opMonry(-10000.00); accountList.get(7).settercard("6222081502051320786", "88888888"); accountList.add(new Account()); accountList.get(8).setterBank( bankList.get(0) ); accountList.get(8).setterAcc(2); accountList.get(8).setterMaster("张三丰"); accountList.get(8).opMonry(-10000.00); accountList.get(8).settercard("6640000010045442002", "88888888"); accountList.get(8).settercard("6640000010045442003", "88888888"); accountList.add(new Account()); accountList.get(9).setterBank( bankList.get(1) ); accountList.get(9).setterAcc(2); accountList.get(9).setterMaster("令狐冲"); accountList.get(9).opMonry(-10000.00); accountList.get(9).settercard("6640000010045441009", "88888888"); accountList.add(new Account()); accountList.get(10).setterBank( bankList.get(2) ); accountList.get(10).setterAcc(2); accountList.get(10).setterMaster("乔峰"); accountList.get(10).opMonry(-10000.00); accountList.get(10).settercard("6630000010033431001", "88888888"); accountList.add(new Account()); accountList.get(11).setterBank( bankList.get(2) ); accountList.get(11).setterAcc(2); accountList.get(11).setterMaster("洪七公"); accountList.get(11).opMonry(-10000.00); accountList.get(11).settercard("6630000010033431008", "88888888"); } public static int seekAccount(String cardnum) { for(int i=0; i<accountList.size(); i++) { for(int j=0; j<accountList.get(i).cardNum.size(); j++) { if(accountList.get(i).cardNum.get(j).equals(cardnum)) { return i; } } } return -1; } public static boolean checkPassword(int accountno,String cardnum, String password) { for(int j=0; j<accountList.get(accountno).cardNum.size(); j++) { if(accountList.get(accountno).cardNum.get(j).equals(cardnum)) { if(accountList.get(accountno).password.get(j).equals(password)) return true; else return false; } } return false; } public static int checkATM(int accountno, String ATMno) { for(int i=0; i<bankList.size(); i++ ) { for(int j=0; j<bankList.get(i).ATMNumlist.size(); j++) { if( bankList.get(i).ATMNumlist.get(j).equals(ATMno) ) { if(bankList.get(i)==accountList.get(accountno).getterBank()) return -1; else return i; } } } return -2; } public static double needkuahangMoney(int accountno, double mon, int atmhefa) { double needmoney; if(mon<=0) { needmoney=0; } else { if(atmhefa==-1) { needmoney=0; } else { needmoney=mon*bankList.get(atmhefa).getterShouxufei(); } } return needmoney; } public static boolean operateMon(int accountno, double mon, double kuahangmoney) { int acc = accountList.get(accountno).getAcc(); double yu = accountList.get(accountno).getterMoney(); double monnum; if(acc==1) { monnum=mon+kuahangmoney; if( (yu-monnum)>=0 ) { accountList.get(accountno).opMonry(monnum); return true; } else return false; } else { if(yu>=mon) { monnum=mon+kuahangmoney; } else if(yu<mon && yu>=0) { monnum=mon+kuahangmoney+(mon-yu)*0.05; } else { monnum=mon+kuahangmoney+mon*0.05; } if( (yu-monnum)>=-50000 ) { accountList.get(accountno).opMonry(monnum); return true; } else return false; } } } class Bank{ private String bankname; private double shouxufei; ArrayList<String> ATMNumlist = new ArrayList<String>(); void setterName(String name) { this.bankname = name; } void setterATM(String ATMno) { ATMNumlist.add(ATMno); } void setterShouxufei(double lixi) { this.shouxufei = lixi; } double getterShouxufei() { return shouxufei; } String getterBankName() { return bankname; } } class Account { private Bank thebank; private String master; private int acc; //账户类型1为借记,2为信用 private double money; ArrayList<String> cardNum = new ArrayList<String>(); ArrayList<String> password = new ArrayList<String>(); void setterBank(Bank bank) { this.thebank = bank; } void setterMaster(String name) { this.master = name; } void settercard(String cardnum, String cardpassword) { cardNum.add(cardnum); password.add(cardpassword); } void setterAcc(int acc) { this.acc = acc; } int getAcc() { return acc; } void opMonry(double moneynum) { /* * if(moneynum < money) { this.money = money - moneynum; return true; } return * false; */ this.money = money - moneynum; } Bank getterBank() { return thebank; } double getterMoney() { return money; } String getterMastername() { return master; } }
对二者的分析
相较于前面数次题目集无穷无尽的设计各种各样不同的类,天花乱坠的类彼此之间的关系,各种各样的继承与多态的使用……面对最后这组较为庞大的工程,在类的设计上反而最为简朴普通。我一共设计了3个类。银行类用来存储银行、ATM机等相关信息和相关处理。账户类用来记录账户、卡号、余额等等相关信息。而主类Main则控制所有流程,包括开始信息的初始化录入,用户的操作,对象调用的修改都由主类进行管理。虽然3个类的关系看似简单,也在功能上给与主类太多,但其实数据与操作的分开,这3个类已经完整的完全达到了,没有必要如再将用户的流程操作一分为二甚至一分为三。因为一体的操作本来也应该统一管理。
关于类的关联关系,在设计中,银行与账户类采用聚合关系。因为大多数时候对银行信息的调用都是账户需要相关信息完成。但在初始化创建的时候也需要在初始化方法中调整相关银行信息。
对于程序的整体流程(以题目集9)为例。首先创建银行列表与账户列表,在通过初始化方法initBank();initAccount();创建具体银行与账户,并将他们存储进入列表之中。
static ArrayList<Bank> bankList = new ArrayList<Bank>();
static ArrayList<Account> accountList = new ArrayList<Account>();
然后开启用户输入的循环,并通过相关内容进行功能选择的判断。对于非法性输入,事实与合法途径方法路径一致,只不过当输入内容合法时返回所需正常值,当输入非法时相关方法会返回-如1予以提示。比如对于查询余额的功能,如下通过seekAccount方法将卡号输入,当正确时accountno为卡号背后对应的账户的列表中的索引号,当错误时该值为-1(因为索引不可能为-1),从而可以判断正误。
if( (accountno=seekAccount(alist[0])) == -1 ) {
System.out.println("Sorry,this card does not exist.");
continue;
}
System.out.printf("业务:查询余额 ¥%.2f\n",accountList.get(accountno).getterMoney());
而该方法的具体实现细节如下。在第一个循环中在账户对象列表中遍历账户对象去找对象账户的各个卡号列表,当匹配上返回账户列表该账户对象的索引 i,否则返回-1
public static int seekAccount(String cardnum) {
for(int i=0; i<accountList.size(); i++) {
for(int j=0; j<accountList.get(i).cardNum.size(); j++) {
if(accountList.get(i).cardNum.get(j).equals(cardnum)) {
return i;
}
}
}
return -1;
}
举一反三,事实上其他功能实现也是上面类似的循环方法与查找逻辑。
三、踩坑心得
在题目集7的题目中,对于接口Comparable<>,在编写代码的过程中尚不熟悉继承该接口后所能提供的方法。因此,在完成了重写该接口所需的compareTo()方法后,却不知道应该使用哪个排序函数
@Override public int compareTo(Shape object) { if(this.getArea() > object.getArea()){ return 1; } else if(this.getArea() < object.getArea() ){ return -1; } return 0; }
最后才明白通过Collections.sort(duilist);实现排序。
在题目集8中其实最大的踩坑是中文输出打字打错了(不是。。。。)技术上最大的麻烦同时也是最大的优势应该是一次检索结果的利用以及信息的返回。比如对于某一次遍历查到了该卡号对应的账户,我需要返回查到,同时也应该返回查到的具体是表中哪个索引的账户,如不这样,后面做其他检查或其他操作的时候又需要重新检索一遍,费时费力并不合理。同时在本题中:
- 如果输入ATM机编号不存在,则输出
Sorry,the ATM's id is wrong. - 如果检测为跨行存取款,则输出
Sorry,cross-bank withdrawal is not supported.
这二者在背后的逻辑操作都是在进行ATM编号的对应查找检索。但找到没找到时应该进行不同的操作。如果采用两个方法遍历基本同样的内容,非常不合适,但二者都是不同情况下的“没找到”才能触发,且找到后因返回找到的内容信息为后面服务。因此,我设计了-1、-2、自然数的返回值用于返回不同的结果,使一轮遍历达到多种效果。
public static int checkATM(int accountno, String ATMno) { for(int i=0; i<bankList.size(); i++ ) { for(int j=0; j<bankList.get(i).ATMNumlist.size(); j++) { if( bankList.get(i).ATMNumlist.get(j).equals(ATMno) ) { if(bankList.get(i)==accountList.get(accountno).getterBank()) return j; else return -1; } } } return -2; }
在这套双层循环中,首先传入账户号和ATM编号。for(int i=0; i<bankList.size(); i++ ) 语句完成通过 i 控制银行列表的遍历。再通过for(int j=0; j<bankList.get(i).ATMNumlist.size(); j++)完成对各个银行 i 的ATM编号的遍历。如果找到与传入的ATM编号相同的编号 if( bankList.get(i).ATMNumlist.get(j).equals(ATMno) ) ,则再判断该银行是否与账户所在银行相同 if(bankList.get(i)==accountList.get(accountno).getterBank())。如果相同的化返回 j ,否则返回-1,意为检测为跨行存取款,否则返回-2意为如果输入ATM机编号不存在。
在题目集8中上述内容的优势还不够显著,因为返回的 j 即ATM机所在该银行的ATM机列表的标号作用还不够大。但在题目集9中,我同样用到了类似的内容,因为题目集9中涉及到跨行存取,且各银行跨行收费不一致,因此三个信息都将会用到
public static int checkATM(int accountno, String ATMno) { for(int i=0; i<bankList.size(); i++ ) { for(int j=0; j<bankList.get(i).ATMNumlist.size(); j++) { if( bankList.get(i).ATMNumlist.get(j).equals(ATMno) ) { if(bankList.get(i)==accountList.get(accountno).getterBank()) return -1; else return i; } } } return -2; }
可以看到在略微的改动中,当银行相同时传回-1,当银行不同时传回银行列表的索引从而可以确定在哪家银行操作。这样一轮函数完成了三层交流,是整道题算法的得意之处
四、改进建议
1、题目集8和题目集9
虽然我个人认为3个类足以较为符合实际且较为职责清晰的完成任务,但事实上主类Main的负担还是太重。在仔细思考后,我觉得还可以将初始化和操作流程分开,这样能更清晰的表达,同时减弱主类的负担。同时还可以加入输入类output从而更加清楚区分职责。
public static void main(String[] args) { initBank(); initAccount(); Scanner scan = new Scanner(System.in); String astr=new String(); while(!(astr=scan.nextLine()).equals("#")){ int accountno; int bankno; String[] alist=astr.split("\\s+");//输入的每行数据用空格隔开,存为数组 if( alist.length==1 ) { if( (accountno=seekAccount(alist[0])) == -1 ) { System.out.println("Sorry,this card does not exist."); continue; } System.out.printf("业务:查询余额 ¥%.2f\n",accountList.get(accountno).getterMoney()); } else if( alist.length==4 ) { if( (accountno=seekAccount(alist[0]))==-1 ) { System.out.println("Sorry,this card does not exist."); continue; } if( !checkPassword(accountno,alist[0],alist[1]) ) { System.out.println("Sorry,your password is wrong."); continue; } if( (bankno=checkATM( accountno, alist[2]))==-2 ) { System.out.println("Sorry,the ATM's id is wrong."); continue; } double amoney = Double.parseDouble(alist[3]); double kuahangmoney=needkuahangMoney(accountno,amoney,bankno); if(!operateMon(accountno,amoney,kuahangmoney)) { System.out.println("Sorry,your account balance is insufficient."); continue; } if(bankno==-1) System.out.printf("业务:取款 %s在%s的%s号ATM机上取款¥%.2f\n",accountList.get(accountno).getterMastername() ,accountList.get(accountno).getterBank().getterBankName() ,alist[2], amoney); else System.out.printf("业务:取款 %s在%s的%s号ATM机上取款¥%.2f\n",accountList.get(accountno).getterMastername() ,bankList.get(bankno).getterBankName() ,alist[2], amoney); System.out.printf("当前余额为¥%.2f\n",accountList.get(accountno).getterMoney()); } } }
五、总结
1、对本轮作业三次题目集而言
可以看到这三次题目集的作业量明显变少,加在一起也一共只有6道题目,但在效果上感觉确是变好很多,希望继续保持(不过好像然后了)。题目集7通过对Comparable接口的继承以及compareTo方法的实现,利用父类列表ArrayList<Shape>,完成对不同子类图形的排序Collections.sort();,从而利用继承与多态完成批量化规范操作。而8、9则没有拘泥于哪个知识点,核心在于对面向对象规范化设计的考察。在于总体设计上对类职责的分配与调用。较为自由的要求反而更加锻炼的整体上的设计思想,和面向对象的设计。
2、对本学期PTA作业集而言
从一开始的“这个学期才正式接触java。对于一门陌生的语言来说,它的语法规则、它的功能特性、它的擅长邻域自然是十分重要的,第一天一开始连输入、输出也确实让我个人不知所措、摸不着头脑。但我们这门课其实叫“面向对象程序设计”而不是叫“java语言程序设计”,老师强调的和教学核心里讲的也是要求我们核心掌握的是面向对象的程序设计思想。我们之前课程安排已经学习了C语言,后面我自己也了解了一点点C++、Python等等,但对于什么是面向对象、什么程序才算面向对象、面向对象有什么用……还是云里雾里。”再到“经过第一、第二阶段的学习后,目前已经对Java有初步了解了。从一开始的对最基本的语法尚不熟悉,到第一阶段结束时逐步掌握Java新带来的一些如继承、多态等特性,和声明式编程内容正则表达式等,再到现在进一步了解更多如接口,以及更多面向对象思想和设计原则如开闭原则等等,对Java的理解的的确确是在不断加深的。比起一开始更多的把这门课当成“java语言程序设计”,现在在简单的完成PTA作业的情况外,也会更多的去考虑我们这门课真正的内容,即“面向对象程序设计”。”然后到现在“课程也来到了尾声。在这个学期的学习中,我从最早的如第一个Blog所讲的对输入输出都感到有点困惑,到逐渐掌握Java的语法并较为熟悉的应用,再到对面向对象的思想进一步加深和了解,这其中可谓收获颇丰。但依然还有许多内容需要我们进一步学习,进一步深入探索。如同最后几节课讲到的建造者模式、桥接模式等等,更让我感到面向对象思想的学习学无止境。我们还有很长的一段路要走。”我确实收获了很多。

浙公网安备 33010602011771号