第三阶段Blog
题目集7~9的总结性Blog
1、前言
一个月又过去了,又到了写blog的时候,相较于前两次Blog,这一次所要分析的内容从原先的侧重于类设计到了这次的侧重于结构设计。在完成作业的时候,尽管题目内提供的指导书十分详细,但在编写程序的途中还是遇到了不少的问题,比如如何设计各个类之间的联系,六大原则的合理运用,功能实现的设计等。
2、设计与分析
①题目集7(7-1)、(7-2)两道题目的递进式设计分析总结
首先看一下这两道题目的具体需求吧
(7-1):
(1)卡片大小排序游戏规则 考虑一款适合于小学生的卡片(Card)排序游戏,其规则为随机发放一些卡片给学生,卡片分为 四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid),并给出各种 卡片的相应参数,要求学生能够迅速求出各卡片的面积大小然后将卡片按照其面积值从大到小进行排 序,同时求出所有卡片的面积之和。
(2)Comparable 接口的应用 图形类设计可参考作业 6-1 的类层次结构,本次作业要求对卡片排序时使用 Comparable 接口, 即 Card 类需要实现 Comparable 接口中的 CompareTo()方法。
(7-2):
(1)卡片大小排序游戏规则 沿袭作业 7-1,本次作业主要对卡片(Card)进行分组游戏,其规则为随机发放一些卡片给学生, 卡片仍然分为四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid), 并给出各种卡片的相应参数,要求学生首先根据卡片类型将所有卡片进行分组(一个类型分为一组, 所以最多四组),然后能够对每组内的卡片根据面积值从大到小进行排序,同时求出该组内所有卡片 的面积之和,最后求出每组卡片面积之和中的最大值。
(2)Comparable、Comparator 接口的应用 图形类设计可参考作业 7-1 的类层次结构(需要进一步完善),本次作业要求对卡片排序时使用 Comparable 接口或 Comparator 接口。
可以看到,这两道题目的要求十分的相近,都是通过设计对应的类去实现卡片游戏,并且在游戏运行过程中要求使用到Comparable接口以完成对应卡片面积的排序,但在输出以及排序方式上有所不同,在实际编辑代码的过程中其实并没有遇到过多的困难,唯一耗时的地方在于如何如何建立一个正确的CardList属性,并使其能够正确的运行sort()方法,将Card数组进行正确的排序并输出
首先先放我的类图和代码吧
(7-1)
package PTAhmwk.图形卡片排序游戏; import java.util.*; 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(); } } class DealCardList{ ArrayList<Card> cardList= new ArrayList<Card>(); DealCardList(){} DealCardList(ArrayList<Integer> list){ for(Integer integer:list){ switch (integer) { case 1: cardList.add(new Card(new Circle(Main.input.nextDouble()))); break; case 2: cardList.add(new Card(new Rectangle(Main.input.nextDouble(), Main.input.nextDouble()))); break; case 3: cardList.add(new Card(new Triangle(Main.input.nextDouble(), Main.input.nextDouble(), Main.input.nextDouble()))); break; case 4: cardList.add(new Card(new Trapezoid(Main.input.nextDouble(), Main.input.nextDouble(), Main.input.nextDouble()))); break; } } } public boolean validate(){ boolean flag = true; for (Card card : cardList) { if (!card.getShape().validate()) { flag = false; break; } } return flag; } public void cardSort(){ Collections.sort(cardList); } public double getAllArea(){ double sumOfArea=0; for (Card card : cardList) { sumOfArea += card.getShape().getArea(); } return sumOfArea; } public void showResult(){ System.out.println("The original list:"); for (Card card : cardList) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } cardSort(); System.out.println("\nThe sorted list:"); for (Card card : cardList) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.printf("\nSum of area:%.2f",getAllArea()); } } class Card implements Comparable<Card>{ private Shape shape; Card(){} Card(Shape shape){ setShape(shape); } public Shape getShape() { return shape; } public void setShape(Shape shape) { this.shape = shape; } public int compareTo(Card card) { if(shape.getArea()>card.getShape().getArea()) return -1; else return 1; } } abstract class Shape{ private String shapeName; Shape(){} Shape(String shapeName){ setShapeName(shapeName); } abstract double getArea(); abstract boolean validate(); public String getShapeName() { return shapeName; } public void setShapeName(String shapeName) { this.shapeName = shapeName; } } class Trapezoid extends Shape{ private double topSide; private double bottomSide; private double height; Trapezoid(){} Trapezoid(double topSide,double bottomSide,double height){ setTopSide(topSide); setBottomSide(bottomSide); setHeight(height); super.setShapeName("Trapezoid"); } public double getArea(){ return (topSide+bottomSide)*height/2; } boolean validate() { return getHeight()>0 && getBottomSide()>0 && getTopSide()>0; } public void setTopSide(double topSide) { this.topSide = topSide; } public void setBottomSide(double bottomSide) { this.bottomSide = bottomSide; } public void setHeight(double height) { this.height = height; } public double getTopSide() { return topSide; } public double getBottomSide() { return bottomSide; } public double getHeight() { return height; } } class Circle extends Shape{ private double radius; Circle(){} Circle(double radius){ setRadius(radius); super.setShapeName("Circle"); } double getArea() { return radius*radius*Math.PI; } boolean validate() { return getRadius()>0; } public void setRadius(double radius) { this.radius = radius; } public double getRadius() { return radius; } } class Rectangle extends Shape{ private double width; private double length; Rectangle(){} Rectangle(double width,double length){ setWidth(width); setLength(length); super.setShapeName("Rectangle"); } double getArea() { return getLength()*getWidth(); } boolean validate() { return (getWidth() >0 && getLength()>0); } public void setWidth(double width) { this.width = width; } public void setLength(double length) { this.length = length; } public double getWidth() { return width; } public double getLength() { return length; } } class Triangle extends Shape{ private double side1; private double side2; private double side3; Triangle(){} Triangle(double side1,double side2,double side3){ setSide1(side1); setSide2(side2); setSide3(side3); super.setShapeName("Triangle"); } double getArea() { double p=(side1+side2+side3)/2; return Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); } boolean validate() { if(side1+side2<=side3||side1+side3<=side2||side2+side3<=side1) { return false; } return !(side1 - side2 >= side3) && !(side1 - side3 >= side2) && !(side2 - side3 >= side1); } public void setSide1(double side1) { this.side1 = side1; } public void setSide2(double side2) { this.side2 = side2; } public void setSide3(double side3) { this.side3 = side3; } }
(7-2)
package PTAhmwk.图形卡片分组游戏; import java.util.*; 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(); } 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(); input.close(); } } class DealCardList{ ArrayList<Card> cardList= new ArrayList<>(); ArrayList<Card> circle = new ArrayList<>(); ArrayList<Card> rectangle =new ArrayList<>(); ArrayList<Card> triangle = new ArrayList<>(); ArrayList<Card> trapezoid = new ArrayList<>(); DealCardList(){} DealCardList(ArrayList<Integer> list){ for(Integer integer:list){ switch (integer) { case 1: cardList.add(new Card(new Circle(Main.input.nextDouble()))); break; case 2: cardList.add(new Card(new Rectangle(Main.input.nextDouble(), Main.input.nextDouble()))); break; case 3: cardList.add(new Card(new Triangle(Main.input.nextDouble(), Main.input.nextDouble(), Main.input.nextDouble()))); break; case 4: cardList.add(new Card(new Trapezoid(Main.input.nextDouble(), Main.input.nextDouble(), Main.input.nextDouble()))); break; } } } public boolean validate(){ boolean flag = true; for (Card card : cardList) { if (!card.getShape().validate()) { flag = false; break; } } return flag; } public void cardSort(){ Collections.sort(circle); Collections.sort(rectangle); Collections.sort(triangle); Collections.sort(trapezoid); } public void cardSeparate(){ for(Card card:cardList){ switch (card.getShape().getShapeName()){ case "Circle": circle.add(card); break; case "Rectangle": rectangle.add(card); break; case "Triangle": triangle.add(card); break; case "Trapezoid": trapezoid.add(card); break; } } } public double getAllArea(ArrayList<Card> list){ double total =0; for(Card card:list){ total += card.getShape().getArea(); } return total; } public double getMaxArea(){ double maxArea = 0; if(getAllArea(circle)>maxArea) maxArea = getAllArea(circle); if(getAllArea(rectangle)>maxArea) maxArea = getAllArea(rectangle); if(getAllArea(triangle)>maxArea) maxArea = getAllArea(triangle); if(getAllArea(trapezoid)>maxArea) maxArea= getAllArea(trapezoid); return maxArea; } public void showResult(){ System.out.println("The original list:"); System.out.print("["); for (Card card : cardList) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]"); System.out.println("\nThe Separated List:"); cardSeparate(); System.out.print("["); for (Card card : circle) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]["); for (Card card : rectangle) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]["); for (Card card : triangle) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]["); for (Card card : trapezoid) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]"); System.out.println("\nThe Separated sorted List:"); cardSort(); System.out.print("["); for (Card card : circle) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]["); for (Card card : rectangle) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]["); for (Card card : triangle) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]["); for (Card card : trapezoid) { System.out.printf("%s:%.2f ", card.getShape().getShapeName(), card.getShape().getArea()); } System.out.print("]"); System.out.printf("\nThe max area:%.2f",getMaxArea()); } } class Card implements Comparable<Card>{ private Shape shape; Card(){} Card(Shape shape){ setShape(shape); } public Shape getShape() { return shape; } public void setShape(Shape shape) { this.shape = shape; } public int compareTo(Card card) { if(shape.getArea()>card.getShape().getArea()) return -1; else return 1; } } abstract class Shape{ private String shapeName; Shape(){} Shape(String shapeName){ setShapeName(shapeName); } abstract double getArea(); abstract boolean validate(); public String getShapeName() { return shapeName; } public void setShapeName(String shapeName) { this.shapeName = shapeName; } } class Trapezoid extends Shape{ private double topSide; private double bottomSide; private double height; Trapezoid(){} Trapezoid(double topSide,double bottomSide,double height){ setTopSide(topSide); setBottomSide(bottomSide); setHeight(height); super.setShapeName("Trapezoid"); } public double getArea(){ return (topSide+bottomSide)*height/2; } boolean validate() { return getHeight()>0 && getBottomSide()>0 && getTopSide()>0; } public void setTopSide(double topSide) { this.topSide = topSide; } public void setBottomSide(double bottomSide) { this.bottomSide = bottomSide; } public void setHeight(double height) { this.height = height; } public double getTopSide() { return topSide; } public double getBottomSide() { return bottomSide; } public double getHeight() { return height; } } class Circle extends Shape{ private double radius; Circle(){} Circle(double radius){ setRadius(radius); super.setShapeName("Circle"); } double getArea() { return radius*radius*Math.PI; } boolean validate() { return getRadius()>0; } public void setRadius(double radius) { this.radius = radius; } public double getRadius() { return radius; } } class Rectangle extends Shape{ private double width; private double length; Rectangle(){} Rectangle(double width,double length){ setWidth(width); setLength(length); super.setShapeName("Rectangle"); } double getArea() { return getLength()*getWidth(); } boolean validate() { return (getWidth() >0 && getLength()>0); } public void setWidth(double width) { this.width = width; } public void setLength(double length) { this.length = length; } public double getWidth() { return width; } public double getLength() { return length; } } class Triangle extends Shape{ private double side1; private double side2; private double side3; Triangle(){} Triangle(double side1,double side2,double side3){ setSide1(side1); setSide2(side2); setSide3(side3); super.setShapeName("Triangle"); } double getArea() { double p=(side1+side2+side3)/2; return Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); } boolean validate() { if(side1+side2<=side3||side1+side3<=side2||side2+side3<=side1) { return false; } return !(side1 - side2 >= side3) && !(side1 - side3 >= side2) && !(side2 - side3 >= side1); } public void setSide1(double side1) { this.side1 = side1; } public void setSide2(double side2) { this.side2 = side2; } public void setSide3(double side3) { this.side3 = side3; } }
对这两个题目稍微做一下总结吧,实际上这两道题主要还是考察了对接口的使用以及接口内方法的重写,实际上并不是很困难,所以并没有花费我多少时间。从我的代码及类图中也可以看到,在不考虑后续的代码维护的情况下,我在(7-2)中的DealCardList类中增加了许多对应不同图形的属性(才不是我偷懒),这样虽然并不满足面对对象编程的开闭原则,但对于这类简单的小程序来说还是可以满足对应需求的,但这也说明了在后续实际的工作中,必须得尽可能的减少此类偷懒的做法,以免在后续程序的维护升级过程中对原先存在的代码进行过多的修改。
②题目集8和题目集9两道ATM机仿真题目的设计思路分析总结
先看一下这两道题目的要求吧
编写一个银行 ATM 机的模拟程序,能够完成用户的存款、取款以及查询余额功能。
怎么说呢,其实在这个学期开始的时候,作业中曾经出现过类似的题目,但对比之下可以发现这一次的题目要求明显细致了许多,要求完成账号的创建存储以及对应的存取操作,并且需要根据题目指导书中所给出的数据为其建立对应的从属关系,即用户-账号-银行卡号结构,这不仅仅是完善了对ATM机的模拟,也为程序的结构设计增添了不小的麻烦,举个很简单的例子,如何在不同的类中访问不同层级的数据,并将输入数据与整个账号结构内的数据进行对比(即如何用银行卡号按用户-账号-银行卡号结构进行查找、对比),并将其按照输入内容进行对应的操作。
老规矩,上代码和类图
7-3 ATM机类结构设计(一)
1 package PTAhmwk.ATM机类结构设计; 2 3 import java.util.ArrayList; 4 import java.util.Objects; 5 import java.util.Scanner; 6 7 public class Main { 8 public static void main(String[] args) { 9 Scanner input = new Scanner(System.in); 10 ArrayList<ATM> atmList = new ArrayList<>(); 11 ChinaUnionPay union = new ChinaUnionPay(atmList); 12 13 String [] nameList ={"杨过","郭靖","张无忌","韦小宝"}; 14 15 ArrayList<User> user = new ArrayList<>();//初始化银行数据 16 for(int i = 0;i<4;i++){ 17 user.add(new User(nameList[i])); 18 } 19 20 21 user.get(0).accountList.add(new Account("3217000010041315709","中国建设银行")); 22 user.get(0).accountList.add(new Account("3217000010041315715","中国建设银行")); 23 user.get(1).accountList.add(new Account("3217000010051320007","中国建设银行")); 24 user.get(2).accountList.add(new Account("3222081502001312389","中国工商银行")); 25 user.get(2).accountList.add(new Account("3222081502001312390","中国工商银行")); 26 user.get(2).accountList.add(new Account("3222081502001312399","中国工商银行")); 27 user.get(3).accountList.add(new Account("3222081502051320785","中国工商银行")); 28 user.get(3).accountList.add(new Account("3222081502051320786","中国工商银行")); 29 //创建账户 30 31 user.get(0).accountList.get(0).cardList.add(new Card("6217000010041315709")); 32 user.get(0).accountList.get(0).cardList.add(new Card("6217000010041315715")); 33 user.get(0).accountList.get(1).cardList.add(new Card("6217000010041315718")); 34 35 user.get(1).accountList.get(0).cardList.add(new Card("6217000010051320007")); 36 37 user.get(2).accountList.get(0).cardList.add(new Card("6222081502001312389")); 38 user.get(2).accountList.get(1).cardList.add(new Card("6222081502001312390")); 39 user.get(2).accountList.get(2).cardList.add(new Card("6222081502001312399")); 40 user.get(2).accountList.get(2).cardList.add(new Card("6222081502001312400")); 41 42 user.get(3).accountList.get(0).cardList.add(new Card("6222081502051320785")); 43 user.get(3).accountList.get(1).cardList.add(new Card("6222081502051320786")); 44 //创建银行卡 45 46 47 48 String atmIn = input.nextLine(); 49 50 while(!atmIn.equals("#")){ 51 String[] inList= atmIn.split("\\s+"); 52 53 if(inList.length != 1) { 54 if (Check.check(user, atmList, inList[0], inList[1], inList[2], inList[3])) { 55 ATM.deal(inList[0], inList[2], Double.parseDouble(inList[3]), user); 56 System.out.printf("当前余额为¥%.2f\n",user.get(ATM.getUser(inList[0],user)).accountList.get(ATM.getAccount(inList[0],user)).balance); 57 } 58 else break; 59 } 60 61 else { 62 ATM.show(inList[0],user); 63 } 64 65 atmIn = input.nextLine(); 66 } 67 68 69 70 } 71 72 73 } 74 75 class Check{ 76 77 public static boolean check(ArrayList<User> userList,ArrayList<ATM> atmList,String cardId,String password,String atmId,String amount){ 78 int flag = -1; 79 80 81 82 83 if(ATM.matchCard(cardId,userList)){ 84 flag = 1; 85 } 86 else { 87 System.out.println("Sorry,this card does not exist."); 88 return false; 89 } 90 91 //检查卡号是否正确 92 93 if(flag == 1 && ATM.matchPassword(password)) { 94 flag = 2; 95 } 96 else { 97 System.out.println("Sorry,your password is wrong."); 98 return false; 99 } 100 //检查密码是否正确 101 if(flag == 2 && ATM.matchAtm(atmId,atmList)){ 102 flag = 3; 103 } 104 else { 105 System.out.println("Sorry,the ATM's id is wrong."); 106 return false; 107 } 108 //检查ATM机编号是否正确 109 if(flag == 3 && ATM.matchAmount(cardId,Double.parseDouble(amount),userList)){ 110 flag =4; 111 } 112 else { 113 System.out.println("Sorry,your account balance is insufficient."); 114 return false; 115 } 116 //检查金额是否正确 117 if(flag == 4 && ATM.matchBank(atmId,cardId,userList,atmList)){ 118 return true; 119 } 120 else{ 121 122 System.out.println("Sorry,cross-bank withdrawal is not supported."); 123 return false; 124 } 125 //检查是否跨行 126 127 } 128 } 129 130 131 132 133 134 class ChinaUnionPay{ 135 Bank ccb; 136 Bank icbc; 137 ArrayList<ATM> atmList; 138 public ChinaUnionPay(ArrayList<ATM> atmList) { 139 this.atmList = atmList; 140 initBank(); 141 } 142 void initBank(){ 143 ccb = new Bank("中国建设银行",4,atmList); 144 icbc = new Bank("中国工商银行",2,atmList); 145 } 146 147 } 148 149 class Bank { 150 String bankName; 151 int atmNum; 152 public Bank(String bankName,int atmNum,ArrayList<ATM> atmList) { 153 this.bankName = bankName; 154 this.atmNum = atmNum; 155 for(int i = 0;i<atmNum;i++){ 156 atmList.add(new ATM(this.bankName,"0"+ (atmList.size()+1))); 157 } 158 } 159 } 160 161 162 163 class User extends ArrayList<User> { 164 String userName; 165 ArrayList<Account> accountList =new ArrayList<>(); 166 public User(String userName) { 167 this.userName = userName; 168 } 169 } 170 171 class Account{ 172 String accountNo; 173 String bankName; 174 double balance = 10000; 175 176 177 ArrayList<Card> cardList = new ArrayList<>(); 178 public Account(String accountNo,String bankName) { 179 this.accountNo = accountNo; 180 this.bankName = bankName; 181 } 182 } 183 184 class Card { 185 String cardNo; 186 String password = "88888888"; 187 188 public Card(String cardNo) { 189 this.cardNo = cardNo; 190 } 191 } 192 193 class ATM { 194 String bankName; 195 String ATMNo; 196 public ATM(String bankName,String ATMNo) { 197 this.bankName = bankName; 198 this.ATMNo = ATMNo; 199 } 200 201 public static void deal(String cardNo,String ATMNo,double amount,ArrayList<User> userList){ 202 203 userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance -= amount; 204 205 show(userList.get(getUser(cardNo, userList)).userName,userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).bankName,ATMNo,amount); 206 }//处理存取操作 207 208 public static boolean matchCard(String cardNo, ArrayList<User> userList) { 209 return getCard(cardNo,userList) != -1; 210 }//检查是否存在银行卡 211 212 public static boolean matchPassword(String password){ 213 return Objects.equals(password, "88888888"); 214 }//检测密码是否正确 215 216 public static boolean matchBank(String ATMNo,String cardNo,ArrayList<User> userList,ArrayList<ATM> atmList){ 217 return Objects.equals(userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).bankName, atmList.get(getAtm(ATMNo, atmList)).bankName); 218 }//检测银行是否正确 219 220 public static boolean matchAmount(String cardNo, double amount,ArrayList<User> userList){ 221 return userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance > amount; 222 }//检测取出金额是否合法 223 224 public static boolean matchAtm(String atmNo,ArrayList<ATM> atmList){ 225 return getAtm(atmNo, atmList) != -1; 226 } 227 228 public static void show(String userName,String bankName,String ATMNo,double amount){ 229 if(amount > 0) 230 System.out.printf("%s在%s的%s号ATM机上取款¥%.2f\n",userName,bankName,ATMNo,amount); 231 else 232 System.out.printf("%s在%s的%s号ATM机上存款¥%.2f\n",userName,bankName,ATMNo,-amount); 233 }//显示存取结果 234 235 public static void show(String cardNo,ArrayList<User> userList){ 236 System.out.printf("¥%.2f\n",userList.get(getUser(cardNo,userList)).accountList.get(getAccount(cardNo,userList)).balance); 237 } 238 239 public static int getCard(String cardNo, ArrayList<User> userList){ 240 for (int i = 0;i< userList.size();i++){ 241 for (int j = 0;j<userList.get(i).accountList.size();j++){ 242 for (int l = 0;l<userList.get(i).accountList.get(j).cardList.size();l++){ 243 if(Objects.equals(userList.get(i).accountList.get(j).cardList.get(l).cardNo, cardNo)) 244 return l; 245 } 246 } 247 248 } 249 250 return -1; 251 }//获取银行卡对应下标 252 253 public static int getAtm(String ATMNo,ArrayList<ATM> atmList){ 254 for(int i = 0;i<atmList.size();i++){ 255 if(Objects.equals(atmList.get(i).ATMNo, ATMNo)) 256 return i; 257 } 258 return -1; 259 }//获取ATM对应下标 260 261 public static int getAccount(String cardNo, ArrayList<User> userList){ 262 for (int i = 0;i< userList.size();i++){ 263 for (int j = 0;j<userList.get(i).accountList.size();j++){ 264 for (int l = 0;l<userList.get(i).accountList.get(j).cardList.size();l++){ 265 if(Objects.equals(userList.get(i).accountList.get(j).cardList.get(l).cardNo, cardNo)) 266 return j; 267 } 268 } 269 } 270 return -1; 271 }//获取账户对应下标 272 273 public static int getUser(String cardNo, ArrayList<User> userList){ 274 for (int i = 0;i< userList.size();i++){ 275 for (int j = 0;j<userList.get(i).accountList.size();j++){ 276 for (int l = 0;l<userList.get(i).accountList.get(j).cardList.size();l++){ 277 if(Objects.equals(userList.get(i).accountList.get(j).cardList.get(l).cardNo, cardNo)) 278 return i; 279 } 280 } 281 } 282 return -1; 283 }//获取用户对应下标 284 285 }
7-1 ATM机类结构设计(二)
1 import java.util.ArrayList; 2 import java.util.Objects; 3 import java.util.Scanner; 4 5 public class Main { 6 public static void main(String[] args) { 7 Scanner input = new Scanner(System.in); 8 ArrayList<ATM> atmList = new ArrayList<>(); 9 ChinaUnionPay union = new ChinaUnionPay(atmList); 10 11 String [] nameList ={"杨过","郭靖","张无忌","韦小宝","张三丰","令狐冲","乔峰","洪七公"}; 12 13 ArrayList<User> user = new ArrayList<>();//初始化银行数据 14 for(int i = 0;i< nameList.length;i++){ 15 user.add(new User(nameList[i])); 16 } 17 18 19 20 user.get(0).accountList.add(new Account("3217000010041315709","中国建设银行","借记账号")); 21 user.get(0).accountList.add(new Account("3217000010041315715","中国建设银行","借记账号")); 22 23 user.get(1).accountList.add(new Account("3217000010051320007","中国建设银行","借记账号")); 24 25 user.get(2).accountList.add(new Account("3222081502001312389","中国工商银行","借记账号")); 26 user.get(2).accountList.add(new Account("3222081502001312390","中国工商银行","借记账号")); 27 user.get(2).accountList.add(new Account("3222081502001312399","中国工商银行","借记账号")); 28 29 user.get(3).accountList.add(new Account("3222081502051320785","中国工商银行","借记账号")); 30 user.get(3).accountList.add(new Account("3222081502051320786","中国工商银行","借记账号")); 31 32 user.get(4).accountList.add(new Account("3640000010045442002","中国建设银行","贷记账号")); 33 34 user.get(5).accountList.add(new Account("3640000010045441009","中国工商银行","贷记账号")); 35 36 user.get(6).accountList.add(new Account("3630000010033431001","中国农业银行","贷记账号")); 37 38 user.get(7).accountList.add(new Account("3630000010033431008","中国农业银行","贷记账号")); 39 //创建账户 40 41 user.get(0).accountList.get(0).cardList.add(new Card("6217000010041315709")); 42 user.get(0).accountList.get(0).cardList.add(new Card("6217000010041315715")); 43 user.get(0).accountList.get(1).cardList.add(new Card("6217000010041315718")); 44 45 user.get(1).accountList.get(0).cardList.add(new Card("6217000010051320007")); 46 47 user.get(2).accountList.get(0).cardList.add(new Card("6222081502001312389")); 48 user.get(2).accountList.get(1).cardList.add(new Card("6222081502001312390")); 49 user.get(2).accountList.get(2).cardList.add(new Card("6222081502001312399")); 50 user.get(2).accountList.get(2).cardList.add(new Card("6222081502001312400")); 51 52 user.get(3).accountList.get(0).cardList.add(new Card("6222081502051320785")); 53 user.get(3).accountList.get(1).cardList.add(new Card("6222081502051320786")); 54 55 user.get(4).accountList.get(0).cardList.add(new Card("6640000010045442002")); 56 user.get(4).accountList.get(0).cardList.add(new Card("6640000010045442003")); 57 58 user.get(5).accountList.get(0).cardList.add(new Card("6640000010045441009")); 59 60 user.get(6).accountList.get(0).cardList.add(new Card("6630000010033431001")); 61 62 user.get(7).accountList.get(0).cardList.add(new Card("6630000010033431008")); 63 //创建银行卡 64 65 66 67 String atmIn = input.nextLine(); 68 69 while(!atmIn.equals("#")){ 70 String[] inList= atmIn.split("\\s+"); 71 72 if(inList.length != 1) { 73 if (Check.check(user, atmList, inList[0], inList[1], inList[2], inList[3])) { 74 ATM.deal(inList[0], inList[2], Double.parseDouble(inList[3]), user,atmList); 75 System.out.printf("当前余额为¥%.2f\n",user.get(ATM.getUser(inList[0],user)).accountList.get(ATM.getAccount(inList[0],user)).balance); 76 } 77 else break; 78 } 79 80 else { 81 ATM.show(inList[0],user); 82 } 83 84 atmIn = input.nextLine(); 85 } 86 87 88 89 } 90 91 92 } 93 94 class Check{ 95 96 public static boolean check(ArrayList<User> userList,ArrayList<ATM> atmList,String cardId,String password,String atmId,String amount){ 97 int flag = -1; 98 99 if(ATM.matchCard(cardId,userList)){ 100 flag = 1; 101 } 102 else { 103 System.out.println("Sorry,this card does not exist."); 104 return false; 105 } 106 107 //检查卡号是否正确 108 109 if(flag == 1 && ATM.matchPassword(password)) { 110 flag = 2; 111 } 112 else { 113 System.out.println("Sorry,your password is wrong."); 114 return false; 115 } 116 //检查密码是否正确 117 if(flag == 2 && ATM.matchAtm(atmId,atmList)){ 118 flag = 3; 119 } 120 else { 121 System.out.println("Sorry,the ATM's id is wrong."); 122 return false; 123 } 124 //检查ATM机编号是否正确 125 if(flag == 3 && ATM.matchAmount(cardId,atmId,Double.parseDouble(amount),userList,atmList)){ 126 flag =4; 127 } 128 else { 129 System.out.println("Sorry,your account balance is insufficient."); 130 return false; 131 } 132 //检查金额是否正确 133 if(flag == 4 && ATM.matchBank(atmId,cardId,userList,atmList)){ 134 return true; 135 } 136 137 return true; 138 } 139 } 140 141 class ChinaUnionPay{ 142 Bank ccb; 143 Bank icbc; 144 Bank abc; 145 ArrayList<ATM> atmList; 146 public ChinaUnionPay(ArrayList<ATM> atmList) { 147 this.atmList = atmList; 148 initBank(); 149 } 150 void initBank(){ 151 ccb = new Bank("中国建设银行",4,atmList,0.02); 152 icbc = new Bank("中国工商银行",2,atmList,0.03); 153 abc = new Bank("中国农业银行",5,atmList,0.04); 154 } 155 156 } 157 158 class Bank { 159 String bankName; 160 int atmNum; 161 double crossBankFee; 162 public Bank(String bankName,int atmNum,ArrayList<ATM> atmList,double crossBankFee) { 163 this.bankName = bankName; 164 this.atmNum = atmNum; 165 this.crossBankFee = crossBankFee; 166 167 for(int i = 0;i<atmNum;i++){ 168 if(atmList.size()<9) { 169 atmList.add(new ATM(this.bankName, "0" + (atmList.size() + 1), this.crossBankFee)); 170 } 171 else { 172 atmList.add(new ATM(this.bankName,Integer.toString((atmList.size() + 1)), this.crossBankFee)); 173 } 174 } 175 } 176 } 177 178 179 180 class User { 181 String userName; 182 ArrayList<Account> accountList =new ArrayList<>(); 183 public User(String userName) { 184 this.userName = userName; 185 } 186 } 187 188 class Account{ 189 String accountNo; 190 String bankName; 191 double balance = 10000; 192 String type; 193 194 ArrayList<Card> cardList = new ArrayList<>(); 195 public Account(String accountNo,String bankName,String type) { 196 this.accountNo = accountNo; 197 this.bankName = bankName; 198 this.type = type; 199 } 200 } 201 202 class Card { 203 String cardNo; 204 String password = "88888888"; 205 206 public Card(String cardNo) { 207 this.cardNo = cardNo; 208 } 209 } 210 211 class ATM { 212 String bankName; 213 String ATMNo; 214 double crossBankFee; 215 216 public ATM(String bankName, String ATMNo, double crossBankFee) { 217 this.bankName = bankName; 218 this.ATMNo = ATMNo; 219 this.crossBankFee = crossBankFee; 220 } 221 222 public static void deal(String cardNo, String ATMNo, double amount, ArrayList<User> userList, ArrayList<ATM> atmList) { 223 224 userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance -= getRealBankFee(cardNo, ATMNo, amount, userList, atmList); 225 226 show(userList.get(getUser(cardNo, userList)).userName, atmList.get(getAtm(ATMNo, atmList)).bankName, ATMNo, amount); 227 }//处理存取操作 228 229 public static boolean matchCard(String cardNo, ArrayList<User> userList) { 230 return getCard(cardNo, userList) != -1; 231 }//检查是否存在银行卡 232 233 public static boolean matchPassword(String password) { 234 return Objects.equals(password, "88888888"); 235 }//检测密码是否正确 236 237 public static boolean matchBank(String ATMNo, String cardNo, ArrayList<User> userList, ArrayList<ATM> atmList) { 238 return Objects.equals(userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).bankName, atmList.get(getAtm(ATMNo, atmList)).bankName); 239 }//检测银行是否正确 240 241 public static boolean matchAmount(String cardNo, String ATMNo, double amount, ArrayList<User> userList, ArrayList<ATM> atmList) { 242 if (userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).type == "借记账号") { 243 return userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance > getRealBankFee(cardNo, ATMNo, amount, userList, atmList); 244 } else { 245 return userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance - getRealBankFee(cardNo, ATMNo, amount, userList, atmList) >= -50000; 246 } 247 }//检测取出金额是否合法 248 249 public static boolean matchAtm(String atmNo, ArrayList<ATM> atmList) { 250 return getAtm(atmNo, atmList) != -1; 251 } 252 253 public static void show(String userName, String bankName, String ATMNo, double amount) { 254 if (amount > 0) 255 System.out.printf("业务:取款 %s在%s的%s号ATM机上取款¥%.2f\n", userName, bankName, ATMNo, amount); 256 else 257 System.out.printf("业务:存款 %s在%s的%s号ATM机上存款¥%.2f\n", userName, bankName, ATMNo, -amount); 258 }//显示存取结果 259 260 public static void show(String cardNo, ArrayList<User> userList) { 261 System.out.printf("业务:查询余额 ¥%.2f\n", userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance); 262 } 263 264 public static int getCard(String cardNo, ArrayList<User> userList) { 265 for (int i = 0; i < userList.size(); i++) { 266 for (int j = 0; j < userList.get(i).accountList.size(); j++) { 267 for (int l = 0; l < userList.get(i).accountList.get(j).cardList.size(); l++) { 268 if (Objects.equals(userList.get(i).accountList.get(j).cardList.get(l).cardNo, cardNo)) 269 return l; 270 } 271 } 272 273 } 274 275 return -1; 276 }//获取银行卡对应下标 277 278 public static int getAtm(String ATMNo, ArrayList<ATM> atmList) { 279 for (int i = 0; i < atmList.size(); i++) { 280 if (Objects.equals(atmList.get(i).ATMNo, ATMNo)) 281 return i; 282 } 283 return -1; 284 }//获取ATM对应下标 285 286 public static int getAccount(String cardNo, ArrayList<User> userList) { 287 for (int i = 0; i < userList.size(); i++) { 288 for (int j = 0; j < userList.get(i).accountList.size(); j++) { 289 for (int l = 0; l < userList.get(i).accountList.get(j).cardList.size(); l++) { 290 if (Objects.equals(userList.get(i).accountList.get(j).cardList.get(l).cardNo, cardNo)) 291 return j; 292 } 293 } 294 } 295 return -1; 296 }//获取账户对应下标 297 298 public static int getUser(String cardNo, ArrayList<User> userList) { 299 for (int i = 0; i < userList.size(); i++) { 300 for (int j = 0; j < userList.get(i).accountList.size(); j++) { 301 for (int l = 0; l < userList.get(i).accountList.get(j).cardList.size(); l++) { 302 if (Objects.equals(userList.get(i).accountList.get(j).cardList.get(l).cardNo, cardNo)) 303 return i; 304 } 305 } 306 } 307 return -1; 308 }//获取用户对应下标 309 310 public static double getRealBankFee(String cardNo, String AtmNo, double amount, ArrayList<User> userList, ArrayList<ATM> atmList) { 311 if (matchBank(AtmNo, cardNo, userList, atmList)) { 312 if (userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).type == "借记账号") { 313 return amount; 314 }//借记卡 315 316 else { 317 if (userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance > amount && userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance > 0) { 318 return amount; 319 } else if (userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance < amount && userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance > 0) { 320 return amount + (amount - userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance) * 0.05; 321 } else { 322 return amount * 1.05; 323 } 324 325 }//贷记卡 326 }//同银行操作 327 else { 328 if (userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).type == "借记账号") { 329 return amount + atmList.get(getAtm(AtmNo, atmList)).crossBankFee * amount; 330 }//借记卡 331 332 else { 333 if (userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance > amount && userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance > 0) { 334 return amount + atmList.get(getAtm(AtmNo, atmList)).crossBankFee * amount; 335 } else if (userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance < amount && userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance > 0) { 336 return amount + (amount - userList.get(getUser(cardNo, userList)).accountList.get(getAccount(cardNo, userList)).balance) * 0.05 + atmList.get(getAtm(AtmNo, atmList)).crossBankFee * amount; 337 } else { 338 return amount * 1.05 + atmList.get(getAtm(AtmNo, atmList)).crossBankFee * amount; 339 340 }//贷记卡 341 342 }//跨行操作 343 }//获取实际取款费用 344 345 } 346 }
从这两次作业的代码和类图可以看出来呀,我这代码写的可真是纯纯的一坨,所有乱七八糟的功能都塞到了ATM类里面,这明显严重违背了单一职责原则以及迪米特法则,让ATM类过多的与程序中其他的类产生了联系与耦合,不仅仅导致了代码的设计过于糟糕,也导致了在编程过程中由于思路混乱导致找不着北,平添了一大堆奇奇怪怪的静态方法(其实在ATM中这一大堆方法中有很大一部分是为了获取对应卡号在CardList中的下标),这些方法明显有更好的实现方式或设计模式,并不需要增加如此之多的静态方法。实际在设计该类的时候也是如此,为了将deal方法放在ATM类中,需要传入存储在另外一个类中的列表,正因为如此,为了操作到对应的数据,平白无故的在完成单一职责的类中增加了一大堆获取下标的方法,导致面多加水,水多加面,使本就不怎么简洁的ATM类雪上加霜。
3、采坑心得
在第8次的作业及第9次作业中,我算是明白了提前进行结构设计的重要性,但凡我在开始动手之前对整个程序的结构进行过规划,都不会在如何在ATM类中进行其他类中进行数据查询这里耗费如此长的时间(说白了我还是个菜逼),在提交作业之后,无论哪次再点开自己曾今写出的代码,我都会想这样一个问题:“是什么让我写出这样的一坨SHIT,怎么会有如此弱智的结构设计。”其实事后想想,只要对数据结构的设计稍加修改就可以避免这样的情况,比如在用户-账号-银行卡号结构对应的各个类中加入对应的下标(实际ATM系统并不可能会有这样的设计,但在不考虑数据库的情况下确实会是更好的选择),在程序设计方面我果然还是差点火候呀。
4、总结
时间过得真快,一下子一个学期就这样过去了,回想第一次Blog作业,那不仅仅是我第一次写OOP相关的内容,同样也是我第一次编写Blog。现在再回去翻看自己曾经编写的代码,不得不感叹在这门课堂上学习到了许多的东西,不仅仅是单纯的Java这门编程语言和面向对象的编程技术,同样也学会了用另一种编程思想去思考对应的需求,同样也学会了通过这种方式去完成实际的应用。在一次次的PTA作业中通过坚持不懈的努力去攻克一个个测试点(这好像不太符合面向对象思想吧),看着一个个绿字变红所带来的成就感是真的使人感到心情愉悦。希望自己能够在将来能够将这门课程中所学到的知识运用到实际的工作中,使自己更加具有想象力,以此克服一个个困难。