PTA题目集7~9小结
前言:
题目集7的主要设计在于,熟练类的继承、多态性使用方法以及接口的应用。题目集8,9主要是针对于类的设计,题目中的各实体类之间的关系,尤其是一对多的组合关系。对实体类的设计要做到单一职责原则,且不能缺少规定的实体类。题目8需要注意的是编程时考虑面向对象中的封装性本题目中的应用以及是否有能够扩展的衍生需求。而题目9需要注意的是在“合成复用原则”及“单一职责原则”基础上,尽量对第8次大作业的程序进行重构,使之符合“开-闭”原则。
设计与分析:
题目集7(7-1)、(7-2)两道题目的递进式设计分析总结
7-1图形卡片排序游戏 (40 分)
输入格式:
- 首先,在一行上输入一串数字(1~4,整数),其中,1代表圆形卡片,2代表矩形卡片,3代表三角形卡片,4代表梯形卡片。各数字之间以一个或多个空格分隔,以“0”结束。例如:
1 3 4 2 1 3 4 2 1 3 0 - 然后根据第一行数字所代表的卡片图形类型,依次输入各图形的相关参数,例如:圆形卡片需要输入圆的半径,矩形卡片需要输入矩形的宽和长,三角形卡片需要输入三角形的三条边长,梯形需要输入梯形的上底、下底以及高。各数据之间用一个或多个空格分隔。
输出格式:
- 如果图形数量非法(小于0)或图形属性值非法(数值小于0以及三角形三边不能组成三角形),则输出
Wrong Format。 - 如果输入合法,则正常输出,所有数值计算后均保留小数点后两位即可。输出内容如下:
- 排序前的各图形类型及面积,格式为
图形名称1:面积值1图形名称2:面积值2 …图形名称n:面积值n,注意,各图形输出之间用空格分开,且输出最后存在一个用于分隔的空格; - 排序后的各图形类型及面积,格式同排序前的输出;
- 所有图形的面积总和,格式为
Sum of area:总面积值。
输入样例1:
在这里给出一组输入。例如:
1 5 3 2 0
输出样例1:
在这里给出相应的输出。例如:
Wrong Format
输入样例2:
在这里给出一组输入。例如:
4 2 1 3 0
3.2 2.5 0.4 2.3 1.4 5.6 2.3 4.2 3.5
输出样例2:
在这里给出相应的输出。例如:
The original list:
Trapezoid:1.14 Rectangle:3.22 Circle:98.52 Triangle:4.02
The sorted list:
Circle:98.52 Triangle:4.02 Rectangle:3.22 Trapezoid:1.14
Sum of area:106.91
输入样例3:
在这里给出一组输入。例如:
4 2 1 3 0
3.2 2.5 0.4 2.3 1.4 5.6 2.3 4.2 8.4
输出样例3:
在这里给出相应的输出。例如:Wrong Format
设计:
主要是由Main函数去对 DealCardList 类中的属性进行判断和操作,其中 DealCardList又对各个图形类在内部进行创建和判断,DealCardList 类内存在showstatus函数,对本次输入的相关内容进行计算和输出。由于代码功能可以提高,具体内容在7-2进行了修改,因此源码就在7-2内分析,7-1不予展示,通过专业软件评测生成类图如下图所示。

7-2 图形卡片分组游戏 (60 分)
掌握类的继承、多态性使用方法以及接口的应用。
输入格式:
- 在一行上输入一串数字(1~4,整数),其中,1代表圆形卡片,2代表矩形卡片,3代表三角形卡片,4代表梯形卡片。各数字之间以一个或多个空格分隔,以“0”结束。例如:
1 3 4 2 1 3 4 2 1 3 0 - 根据第一行数字所代表的卡片图形类型,依次输入各图形的相关参数,例如:圆形卡片需要输入圆的半径,矩形卡片需要输入矩形的宽和长,三角形卡片需要输入三角形的三条边长,梯形需要输入梯形的上底、下底以及高。各数据之间用一个或多个空格分隔。
输出格式:
- 如果图形数量非法(<=0)或图形属性值非法(数值<0以及三角形三边不能组成三角形),则输出
Wrong Format。 - 如果输入合法,则正常输出,所有数值计算后均保留小数点后两位即可。输出内容如下:
- 排序前的各图形类型及面积,格式为
[图形名称1:面积值1图形名称2:面积值2 …图形名称n:面积值n ],注意,各图形输出之间用空格分开,且输出最后存在一个用于分隔的空格,在结束符“]”之前; - 输出分组后的图形类型及面积,格式为
[圆形分组各图形类型及面积][矩形分组各图形类型及面积][三角形分组各图形类型及面积][梯形分组各图形类型及面积],各组内格式为图形名称:面积值。按照“Circle、Rectangle、Triangle、Trapezoid”的顺序依次输出; - 各组内图形排序后的各图形类型及面积,格式同排序前各组图形的输出;
- 各组中面积之和的最大值输出,格式为
The max area:面积值。
输入样例1:
在这里给出一组输入。例如:
1 5 3 2 0
输出样例1:
在这里给出相应的输出。例如:
Wrong Format
输入样例2:
在这里给出一组输入。例如:
4 2 1 3 0
3.2 2.5 0.4 2.3 1.4 5.6 2.3 4.2 3.5
输出样例2:
在这里给出相应的输出。例如:
The original list:
[Trapezoid:1.14 Rectangle:3.22 Circle:98.52 Triangle:4.02 ]
The Separated List:
[Circle:98.52 ][Rectangle:3.22 ][Triangle:4.02 ][Trapezoid:1.14 ]
The Separated sorted List:
[Circle:98.52 ][Rectangle:3.22 ][Triangle:4.02 ][Trapezoid:1.14 ]
The max area:98.52
输入样例3:
在这里给出一组输入。例如:
2 1 2 1 1 3 3 4 4 1 1 1 2 1 0
2.3 3.5 2.5 4.5 2.1 2.6 8.5 3.2 3.1 3.6 8.5 7.5 9.1245 6.5 3.4 10.2 11.2 11.6 15.4 5.8 2.13 6.2011 2.5 6.4 18.65
输出样例3:
在这里给出相应的输出。例如:
The original list:
[Rectangle:8.05 Circle:19.63 Rectangle:9.45 Circle:21.24 Circle:226.98 Triangle:4.65 Triangle:29.80 Trapezoid:50.49 Trapezoid:175.56 Circle:105.68 Circle:14.25 Circle:120.81 Rectangle:16.00 Circle:1092.72 ]
The Separated List:
[Circle:19.63 Circle:21.24 Circle:226.98 Circle:105.68 Circle:14.25 Circle:120.81 Circle:1092.72 ][Rectangle:8.05 Rectangle:9.45 Rectangle:16.00 ][Triangle:4.65 Triangle:29.80 ][Trapezoid:50.49 Trapezoid:175.56 ]
The Separated sorted List:
[Circle:1092.72 Circle:226.98 Circle:120.81 Circle:105.68 Circle:21.24 Circle:19.63 Circle:14.25 ][Rectangle:16.00 Rectangle:9.45 Rectangle:8.05 ][Triangle:29.80 Triangle:4.65 ][Trapezoid:175.56 Trapezoid:50.49 ]
The max area:1601.31
输入样例4:
在这里给出一组输入。例如:
1 1 3 0
6.5 12.54 3.6 5.3 6.4
输出样例4:
在这里给出相应的输出。例如:
The original list:
[Circle:132.73 Circle:494.02 Triangle:9.54 ]
The Separated List:
[Circle:132.73 Circle:494.02 ][][Triangle:9.54 ][]
The Separated sorted List:
[Circle:494.02 Circle:132.73 ][][Triangle:9.54 ][]
The max area:626.75
分析:
7-2针对输出的内容需要进行分组,输出时需要对不同的图形内部进行一次排序,最终还需要将所有面积进行想加,设计时,需要根据实体类中大部分的共同点设计一个抽象父类,然后在通过一个大类来对里面不同的类进行使用。通过多态实现不同类之间的区别,最后在大类中对所需要的内容进行修改和操作,编写一个合适的函数去统计输出。该函数需要一个处理函数针对每次输入的类别进行判别分类,然后排序函数只需要针对父类类型的进行排序,就可以实现所进行的分组排序。
源代码:
import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; public class Main { public static final 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(); } if(list.size()==0) { System.out.println("Wrong Format"); System.exit(0); } DealCardList dealCardList = new DealCardList(list); if(!dealCardList.validate()){ System.out.println("Wrong Format"); System.exit(0); } dealCardList.showResult(); } } class DealCardList { ArrayList<Card> cardList=new ArrayList<Card>(); ArrayList<Card> CircleList=new ArrayList<Card>(); ArrayList<Card> RectangleList=new ArrayList<Card>(); ArrayList<Card> TriangleList=new ArrayList<Card>(); ArrayList<Card> TrapezoidList=new ArrayList<Card>(); DealCardList(){ } DealCardList(ArrayList<Integer>list) { int i=0; for(i=0;i<list.size();i++) { if(list.get(i)==1) { double raduis=Main.input.nextDouble(); Circle c=new Circle(raduis); Card card=new Card(c); cardList.add(card); } else if(list.get(i)==2) { double l=Main.input.nextDouble(); double w=Main.input.nextDouble(); Rectangle r=new Rectangle(l,w); Card card=new Card(r); cardList.add(card); } else if(list.get(i)==3) { double s1=Main.input.nextDouble(); double s2=Main.input.nextDouble(); double s3=Main.input.nextDouble(); Triangle tri=new Triangle(s1,s2,s3); Card card=new Card(tri); cardList.add(card); } else if(list.get(i)==4) { double top=Main.input.nextDouble(); double bottom=Main.input.nextDouble(); double hight=Main.input.nextDouble(); Trapezoid tra=new Trapezoid(top,bottom,hight); Card card=new Card(tra); cardList.add(card); } } } public boolean validate() { int i; for(i=0;i<cardList.size();i++) { if(cardList.get(i).shape.validate()==false) { return false; } } return true; } public void cardSort(ArrayList<Card> a) { Collections.sort(a); } public double getAllArea(ArrayList<Card> a) { int i; double allArea=0; for(i=0;i<a.size();i++) { allArea=allArea+a.get(i).shape.getArea(); } return allArea; } public void sort_In_FourList() { int i; for(i=0;i<cardList.size();i++) { if(cardList.get(i).shape.getShapeName().equals("Circle")) CircleList.add(cardList.get(i)); else if(cardList.get(i).shape.getShapeName().equals("Rectangle")) RectangleList.add(cardList.get(i)); else if(cardList.get(i).shape.getShapeName().equals("Triangle")) TriangleList.add(cardList.get(i)); else if(cardList.get(i).shape.getShapeName().equals("Trapezoid")) TrapezoidList.add(cardList.get(i)); } } public double getMaxArea() { int i; double max; double s1,s2,s3,s4; s1=getAllArea(CircleList); s2=getAllArea(RectangleList); s3=getAllArea(TriangleList); s4=getAllArea(TrapezoidList); max=s1; if(s2>s1) max=s2; if(s3>max) max=s3; if(s4>max) max=s4; return max; } public void show(ArrayList<Card> a) { int i; System.out.print("["); for(i=0;i<a.size();i++) { System.out.printf("%s:%.2f ",a.get(i).shape.getShapeName(),a.get(i).shape.getArea()); } System.out.printf("]"); } public void show_fourList() { show(CircleList); show(RectangleList); show(TriangleList); show(TrapezoidList); } public void showResult() { int i; System.out.println("The original list:"); show(cardList); System.out.printf("\nThe Separated List:\n"); sort_In_FourList(); show_fourList(); System.out.println("\nThe Separated sorted List:"); cardSort(CircleList); cardSort(RectangleList); cardSort(TriangleList); cardSort(TrapezoidList); show_fourList(); System.out.printf("\nThe max area:%.2f",getMaxArea()); } } abstract class Shape { private String ShapeName; Shape() { } Shape(String Shapename) { this.ShapeName=Shapename; } public String getShapeName() { return ShapeName; } public void setShapeName(String shapeName) { ShapeName = shapeName; } public abstract double getArea(); public abstract boolean validate(); public String toString() { return ShapeName; } } 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_other) { if(this.shape.getArea()<card_other.shape.getArea()) return 1; else if(this.shape.getArea()>card_other.shape.getArea()) return -1; else return 0; } } class Circle extends Shape{ private double radius; Circle() { super.setShapeName("Circle"); } Circle(double radius) { this.radius=radius; super.setShapeName("Circle"); } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } @Override public double getArea() { return Math.PI*radius*radius; } @Override public boolean validate() { if(radius>0) return true; else return false; } } class Rectangle extends Shape{ double width,length; Rectangle() { super.setShapeName("Rectangle"); } Rectangle(double length,double width) { this.length=length; this.width=width; super.setShapeName("Rectangle"); } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getLength() { return length; } public void setLength(double length) { this.length = length; } @Override public double getArea() { return length*width; } @Override public boolean validate() { if(width>0&&length>0) return true; else return false; } } class Triangle extends Shape{ double side1,side2,side3; Triangle() { super.setShapeName("Triangle"); } Triangle(double side1,double side2,double side3) { this.side1=side1; this.side2=side2; this.side3=side3; super.setShapeName("Triangle"); } @Override public double getArea() { double p=(side1+side2+side3)/2; double area=Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); return area; } @Override public boolean validate() { if(side1<=0||side2<=0||side3<=0) return false; if(side1+side2>side3&&side1+side3>side2&&side2+side3>side1) return true; return false; } } class Trapezoid extends Shape{ double topSide,bottomSide,hight; Trapezoid() { super.setShapeName("Trapezoid"); } Trapezoid(double topSide,double bottomSide,double hight) { super.setShapeName("Trapezoid"); this.bottomSide=bottomSide; this.hight=hight; this.topSide=topSide; } @Override public double getArea() { return (topSide+bottomSide)*hight/2; } @Override public boolean validate() { if(topSide<0||bottomSide<0||hight<0) return false; return true; } }
类图如下图所示:

两道题目设计的比较:
两次题目的设计源于第一次设计时有无对扩展性的考虑,增加新的需求和内容时,是否需要进行大量修改删减。如果设计时,继承内容的占比不是很大,只有部分实体之间才用了继承的话,那么对于修改时,便不会因为父类未实现,需要修改分类,而使得整个程序进行大量修改。
其次通过接口实现的功能,只要对接口函数进行一次覆盖,就可以重新完成一次新的要求。不会因为继承太多而导致新功能受原本设计时的结构影响,两题圈复杂度评估。
专业软件评测结果:
7-1:

7-2:

总体而言差不多,主要是结构类似,只是增加了函数处理以及接口的修改。
题目集8和题目集9两道ATM机仿真题目的设计思路分析总结
7-3 ATM机类结构设计(一) (100 分)
输入格式:
每一行输入一次业务操作,可以输入多行,最终以字符#终止。具体每种业务操作输入格式如下:
- 存款、取款功能输入数据格式:
卡号 密码 ATM机编号 金额(由一个或多个空格分隔), 其中,当金额大于0时,代表取款,否则代表存款。 - 查询余额功能输入数据格式:
卡号
输出格式:
①输入错误处理
- 如果输入卡号不存在,则输出
Sorry,this card does not exist.。 - 如果输入ATM机编号不存在,则输出
Sorry,the ATM's id is wrong.。 - 如果输入银行卡密码错误,则输出
Sorry,your password is wrong.。 - 如果输入取款金额大于账户余额,则输出
Sorry,your account balance is insufficient.。 - 如果检测为跨行存取款,则输出
Sorry,cross-bank withdrawal is not supported.。
②取款业务输出
输出共两行,格式分别为:
[用户姓名]在[银行名称]的[ATM编号]上取款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
③存款业务输出
输出共两行,格式分别为:
[用户姓名]在[银行名称]的[ATM编号]上存款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
④查询余额业务输出
¥[金额]
金额保留两位小数。
输入样例1:
在这里给出一组输入。例如:
6222081502001312390 88888888 06 -500.00
#
输出样例1:
在这里给出相应的输出。例如:
张无忌在中国工商银行的06号ATM机上存款¥500.00
当前余额为¥10500.00
输入样例2:
在这里给出一组输入。例如:
6217000010041315709 88888888 02 3500.00
#
输出样例2:
在这里给出相应的输出。例如:
杨过在中国建设银行的02号ATM机上取款¥3500.00
当前余额为¥6500.00
输入样例3:
在这里给出一组输入。例如:
6217000010041315715
#
输出样例3:
在这里给出相应的输出。例如:
¥10000.00
输入样例4:
在这里给出一组输入。例如:
6222081502001312390 88888888 06 -500.00
6222081502051320786 88888888 06 1200.00
6217000010041315715 88888888 02 1500.00
6217000010041315709 88888888 02 3500.00
6217000010041315715
#
输出样例4:
在这里给出相应的输出。例如:
张无忌在中国工商银行的06号ATM机上存款¥500.00
当前余额为¥10500.00
韦小宝在中国工商银行的06号ATM机上取款¥1200.00
当前余额为¥8800.00
杨过在中国建设银行的02号ATM机上取款¥1500.00
当前余额为¥8500.00
杨过在中国建设银行的02号ATM机上取款¥3500.00
当前余额为¥5000.00
¥5000.00
ATM机类结构设计(二) (100 分)
设计ATM仿真系统,具体要求参见作业说明。
输入格式:
每一行输入一次业务操作,可以输入多行,最终以字符#终止。具体每种业务操作输入格式如下:
- 取款功能输入数据格式:
卡号 密码 ATM机编号 金额(由一个或多个空格分隔) - 查询余额功能输入数据格式:
卡号
输出格式:
①输入错误处理
- 如果输入卡号不存在,则输出
Sorry,this card does not exist.。 - 如果输入ATM机编号不存在,则输出
Sorry,the ATM's id is wrong.。 - 如果输入银行卡密码错误,则输出
Sorry,your password is wrong.。 - 如果输入取款金额大于账户余额,则输出
Sorry,your account balance is insufficient.。
②取款业务输出
输出共两行,格式分别为:
业务:取款 [用户姓名]在[银行名称]的[ATM编号]上取款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
③查询余额业务输出
业务:查询余额 ¥[金额]
金额保留两位小数。
输入样例1:
在这里给出一组输入。例如:
6222081502001312390 88888888 06 500.00
#
输出样例1:
在这里给出相应的输出。例如:
业务:取款 张无忌在中国工商银行的06号ATM机上取款¥500.00
当前余额为¥9500.00
输入样例2:
在这里给出一组输入。例如:
6217000010041315709 88888888 06 3500.00
#
输出样例2:
在这里给出相应的输出。例如:
业务:取款 杨过在中国工商银行的06号ATM机上取款¥3500.00
当前余额为¥6395.00
输入样例3:
在这里给出一组输入。例如:
6217000010041315715
#
输出样例3:
在这里给出相应的输出。例如:
业务:查询余额 ¥10000.00
输入样例4:
在这里给出一组输入。例如:
6222081502001312390 88888888 01 500.00
6222081502051320786 88888888 06 1200.00
6217000010041315715 88888888 02 1500.00
6217000010041315709 88888888 02 3500.00
6217000010041315715
#
输出样例4:
在这里给出相应的输出。例如:
业务:取款 张无忌在中国建设银行的01号ATM机上取款¥500.00
当前余额为¥9490.00
业务:取款 韦小宝在中国工商银行的06号ATM机上取款¥1200.00
当前余额为¥8800.00
业务:取款 杨过在中国建设银行的02号ATM机上取款¥1500.00
当前余额为¥8500.00
业务:取款 杨过在中国建设银行的02号ATM机上取款¥3500.00
当前余额为¥5000.00
业务:查询余额 ¥5000.00
输入样例5:
在这里给出一组输入。例如:
6640000010045442002 88888888 09 3000
6640000010045442002 88888888 06 8000
6640000010045442003 88888888 01 10000
6640000010045442002
#
输出样例5:
在这里给出相应的输出。例如:
业务:取款 张三丰在中国农业银行的09号ATM机上取款¥3000.00
当前余额为¥6880.00
业务:取款 张三丰在中国工商银行的06号ATM机上取款¥8000.00
当前余额为¥-1416.00
业务:取款 张三丰在中国建设银行的01号ATM机上取款¥10000.00
当前余额为¥-11916.00
业务:查询余额 ¥-11916.00
import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { int i; Scanner input = new Scanner(System.in); StringBuilder in=new StringBuilder(); Data data=new Data(); data.Inint_bank(); data.Inint_ATM(); data.Inint_Info(); while(true) { String scanf=input.nextLine(); scanf=scanf.trim(); if(scanf.equals("#")==true) break; in.append(scanf+"|"); } input.close(); String in_scanf=in.toString(); String []splite=in_scanf.split("[\\|]"); for(i=0;i<splite.length;i++) { if(i!=0) System.out.println(""); if(splite[i].length()>19) { if(data.validate2(splite[i])==false) { System.exit(0); } } else if(splite[i].length()==19) { if(data.validate1(splite[i])==false) { System.exit(0); } } else { System.exit(0); } } } } class Data{ BankList list; Bank JianShe; Bank GongShang; Bank Nongye; public void Inint_bank() { list=new BankList("中国银联",0.05,50000); JianShe=new Bank("中国建设银行",0.02); GongShang=new Bank("中国工商银行",0.03); Nongye=new Bank("中国农业银行",0.04); list.bank.add(JianShe); list.bank.add(GongShang); list.bank.add(Nongye); } public void Inint_ATM() { JianShe.Atm.add("01"); JianShe.Atm.add("02"); JianShe.Atm.add("03"); JianShe.Atm.add("04"); GongShang.Atm.add("05"); GongShang.Atm.add("06"); Nongye.Atm.add("07"); Nongye.Atm.add("08"); Nongye.Atm.add("09"); Nongye.Atm.add("10"); Nongye.Atm.add("11"); } public void Inint_Info() { Info info1=new Info("杨过",10000.00,"借记账号"); info1.add_id("6217000010041315709","88888888"); info1.add_id("6217000010041315715","88888888"); Info info2=new Info("杨过",10000.00,"借记账号"); info2.add_id("6217000010041315718","88888888"); Info info3=new Info("郭靖",10000.00,"借记账号"); info3.add_id("6217000010051320007","88888888"); Info info_0=new Info("张三丰",10000.00,"贷记账号"); info_0.add_id("6640000010045442002","88888888" ); info_0.add_id("6640000010045442003","88888888" ); JianShe.info.add(info1); JianShe.info.add(info2); JianShe.info.add(info3); JianShe.info.add(info_0); Info info4=new Info("张无忌",10000.00,"借记账号"); info4.add_id("6222081502001312389","88888888"); Info info5=new Info("张无忌",10000.00,"借记账号"); info5.add_id("6222081502001312390","88888888"); Info info6=new Info("张无忌",10000.00,"借记账号"); info6.add_id("6222081502001312399","88888888"); info6.add_id("6222081502001312400","88888888"); Info info7=new Info("韦小宝",10000.00,"借记账号"); info7.add_id("6222081502051320785","88888888"); Info info8=new Info("韦小宝",10000.00,"借记账号"); info8.add_id("6222081502051320786","88888888"); Info info_1=new Info("令狐冲",10000.00,"贷记账号"); info_1.add_id("6640000010045441009", "88888888"); GongShang.info.add(info4); GongShang.info.add(info5); GongShang.info.add(info6); GongShang.info.add(info7); GongShang.info.add(info8); GongShang.info.add(info_1); Info info_2_1 = new Info("乔峰",10000.00,"贷记账号"); info_2_1.add_id("6630000010033431001", "88888888"); Info info_2_2 = new Info("洪七公",10000.00,"贷记账号"); info_2_2.add_id("6630000010033431008", "88888888"); Nongye.info.add(info_2_1); Nongye.info.add(info_2_2); } public boolean validate1(String x) { int i,j; if(this.validate_id(x)!=null) { for(i=0;i<list.bank.size();i++) { for(j=0;j<list.bank.get(i).info.size();j++) { if((list.bank.get(i).info.get(j).validate(x))==true) { System.out.printf("业务:查询余额 "+"¥%.2f",list.bank.get(i).info.get(j).money); return true; } } } } return false; } public boolean validate2(String x) { int i; Bank judge1; //账户所在银行 Bank judge2; //ATM所归属的银行 String name; String personName=null; double money=0; x=x.replaceAll("[\\s][\\s]"," "); String []spilte=x.split("[\\s]"); if(spilte.length==4) { judge1=validate_id(spilte[0]); if(judge1==null) return false; judge2=validate_atm(spilte[2]); if(judge2==null) return false; if(validate_acount(spilte[0], spilte[1])==false) return false; if(validate_judge(judge1,judge2)==1) { money=validate_money(judge1,spilte[0],Double.parseDouble(spilte[3]),0); if(money==-50001) return false; } else { money=validate_money(judge1,spilte[0],Double.parseDouble(spilte[3]),judge2.profit); if(money==-50001) return false; } name=judge2.name; for(i=0;i<judge1.info.size();i++) { if(judge1.info.get(i).validate(spilte[0])==true) personName=judge1.info.get(i).host; } System.out.printf("业务:取款 %s在%s的%s号ATM机上取款¥%.2f\n",personName,name,spilte[2],Double.parseDouble(spilte[3])); System.out.printf("当前余额为¥%.2f",money); return true; } else return false; } public double validate_money(Bank x,String id,double y,double rate) { int i; double money=0; for(i=0;i<x.info.size();i++) { if(x.info.get(i).validate(id)==true) { if(x.Store_Money(x.info.get(i),y,rate)==false) return -50001; money=x.info.get(i).money; } } return money; } public int validate_judge(Bank x,Bank y) { if(x.name.equals(y.name)) return 1; else return 0; } public Bank validate_atm(String x) { int i; for(i=0;i<list.bank.size();i++) { if(list.bank.get(i).validate(x)==true) return list.bank.get(i); } System.out.println("Sorry,the ATM's id is wrong."); return null; } public boolean validate_acount(String x,String y) { int i,j; for(i=0;i<list.bank.size();i++) { for(j=0;j<list.bank.get(i).info.size();j++) { if(list.bank.get(i).info.get(j).validate(x, y)==true) return true; } } System.out.println("Sorry,your password is wrong."); return false; } public Bank validate_id(String x) { int i,j; for(i=0;i<list.bank.size();i++) { for(j=0;j<list.bank.get(i).info.size();j++) { if(list.bank.get(i).info.get(j).validate(x)==true) return list.bank.get(i); } } System.out.println("Sorry,this card does not exist."); return null; } } class BankList{ String institution_name; ArrayList<Bank>bank=new ArrayList<Bank>(); double profit; int maxprofit; BankList(String name,double profit,int max) { this.institution_name=name; this.profit=profit; this.maxprofit=max; } } class Bank{ String name; double profit; ArrayList<Info> info; ArrayList<String> Atm; Bank(String name,double profit) { this.name=name; this.profit=profit; info=new ArrayList<Info>(); Atm=new ArrayList<String>(); } public boolean Store_Money(Info info,double Money,double rate) { double sum=0; if(Money>=0) { if(Money*(1+rate)<=info.money) { info.money=info.money-Money*(1+rate); return true; } else { if(info.type.equals("借记账号")) { System.out.println("Sorry,your account balance is insufficient."); return false; } else if(info.type.equals("贷记账号")) { if(info.money>0) //账户内有钱 { sum=info.money-Money*(1+rate)-(Money-info.money)*0.05; if(0-sum<50000) { info.money=sum; return true; } else { System.out.println("Sorry,your account balance is insufficient."); return false; } } else //账户内无钱 { sum=info.money-Money*(1+rate)-Money*0.05; if(0-sum<50000) { info.money=sum; return true; } else { System.out.println("Sorry,your account balance is insufficient."); return false; } } } } return false; } else { return false; } } public boolean validate(String Atmid) { int i; for(i=0;i<Atm.size();i++) { if(Atm.get(i).equals(Atmid)==true) return true; } return false; } } class Info{ ArrayList<String> id; String host; String type; ArrayList<String>password; double money; Info(String host,double Money,String CardType) { this.host=host; this.money=Money; this.type=CardType; id=new ArrayList<String>(); password=new ArrayList<String>(); } public void add_id(String uid,String upassword) { id.add(uid); password.add(upassword); } public boolean validate(String uid) { int i; for(i=0;i<id.size();i++) { if(this.id.get(i).equals(uid)==true) return true; } return false; } public boolean validate(String uid,String upassword) { int i; for(i=0;i<id.size();i++) { if(id.get(i).equals(uid)==true&&password.get(i).equals(upassword)==true) return true; } return false; } }
类图:

比较:
第二次与第一次不同在于属性上不同,结构上也略有不同,主要在于题目所对应的需求不一样,第一题并未对卡进行划分,也不实现跨行转账,因此功能模式比较单一,使用简单的两层结构就能对其进行实现而第二次设计增加了透支消费,卡类别划分,对不同卡实现同一件事情的结果不同,最主要时需要采用开闭原则,对扩展开放,对修改关闭。因此类别设计的时候就需要增加一个类来对银行功能的扩展,而对修改数据进行关闭,对后续如果要对银行机构产生相关行为,依然能够使用该模式进行扩展。
专业软件对于圈复杂度的评估:
题目集8:

题目集9:

采坑心得:
对于扩展性并能设计的很完善,以至于做扩展时,需要对原本代码的一部分进行改动(ATM类设计),从而使的设计的结构不是很好,对于多种情况应变并不灵活,所以需要在编写前进行可扩展分析,针对哪些情况可以留下适当的内容用于扩展,而不是在ATM类中对卡类别划分时,各个合法判断函数需要全部重写,不然对原本非法(透支消费)的内容,此次合法的数据判定就需要大量改动,对于扩展性的开闭原则并不能完美实现,存在一定问题。以后看待问题时,需要充分考虑到扩展性再进行设计。
改进建议:
(1):需要减少上帝类的设计,把功能进行划分,做到一个实体做一件事,做到合理分配,做到面向对象的设计思想。
(2):需要对代码进行优化,圈复杂度分析中,还是能够看出有一些圈复杂度还是较大。
(3):对于多个类的调用的类,经量增加一个数据类,来进行数据封装,调用时对数据进行改动,不需要在调用类中对多个子类进行组合。
(4):设计前需要针对可能存在的扩展进行开闭原则设计。
(5):代码编写时间较长,需要提高。
总结:
本次题目集需要对父类,子类的继承,封装,多态,接口使用等运用。重点对于类的设计方面有更多要求。三次作业针对两个事例题目进行编写和扩展,如果编写前设计不够良好,则需要不断在后续需求中,较为大量修改其中源码,本次小结并未给出一次通过的代码。对于对教师、课程、作业、实验、课上及课下组织方式等方面的改进方面,希望能够实验中的代码给出一个实现后的演示,在实验五开始时,农夫过河类的动画想的很复杂,思考了很长时间坐出的内容和所想差距很大。如果能够有演示代码就好了。课堂内容很多偏向于结构设计,模式设计等,能够对语法外的内容进行大量扩充。总体而言,教学模式还是很不错的。

浙公网安备 33010602011771号