PTA题目集7-9总结
一、前言
题目集七:该题集为轮到图形卡片排序游戏题,主要考查的知识点有类的继承,ArrayList泛型的使用,Compabale接口的运用,多态的使用方法以及接口的应用,难度较难,题量适中;
题目集八:这个题集都为一道ATM机类结构设计题,主要考查的知识点有各实体类之间的关系,尤其是一对多的组合关系。对实体类的设计要做到单一职责原则,且不能缺少规定的实体类。编程时考虑面向对象中的封装性本题目中的应用以及是否有能够扩展 的衍生需求。对我来说这道题难度很大,开始有点无从下手,有太多的组合和关联,让我逻辑很混乱。
题目集九:这个题集都为一道ATM机类结构设计题,主要考查的知识点有各实体类之间的关系,尤其是一对多的组合关系。对实体类的设计要做到单一职责原则,且不能缺少规定的实体类。在“合成复用原则”及“单一职责原则”基础上,尽量对上次作业的程 序进行重构,使之符合 “开-闭”原则。在题集八的基础上,题集九就稍微更简单了一些,但是还是很有难度,但相比于题集八思路清晰了许多。
二、设计与分析
(1):题目集七(7-1)
类图及复杂分析图如下:
本题要求考虑一款适合于小学生的卡片(Card)排序游戏,其规则为随机发放一些卡片给学生,卡片分为 四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid),并给出各种 卡片的相应参数,要求学生能够迅速求出各卡片的面积大小然后将卡片按照其面积值从大到小进行排 序,同时求出所有卡片的面积之和。
为实现该要求,先创建Shape抽象类,类中有构造方法,得到,设置图形名字的方法,计算面积方法,判断是否合法方法和toString方法;然后创建Circle,Rectangle,Triangle,Trapezoid这四个类,然后这四个类都继承Shape类,然后重写Shape类中的方法;创建Card类,Card类关联Shape类,shape类作为Card类的属性,Card类中有他的构造方法和得到图形的方法以及比较方法;最后创建DealCardList类,DealCardList类关联Card类,DealCardList类中使用ArrayList泛型,将图片对象放入该数组列表中;主要实现了对面积的计算,排序以及对同类型的面积求和功能。
各类的创建:
class Card { Shape shape; Card() { } public Card(Shape shape) { // super(); this.shape = shape; } public Shape getShape() { return shape; } public void setShape(Shape shape) { this.shape = shape; } } abstract class Shape { String shapeName; Shape() { } public Shape(String shapeName) { this.shapeName = shapeName; } public String getShapeName() { return shapeName; } public void setShapeName(String shapeName) { this.shapeName = shapeName; } public abstract double getArea(); public abstract boolean validate(); public abstract String toString(); } class Circle extends Shape { private double radius; Circle() { } public Circle(double radius) { this.radius = radius; } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } @Override public double getArea() { // TODO Auto-generated method stub return Math.PI * radius * radius; } @Override public boolean validate() { // TODO Auto-generated method stub if (radius < 0) return false; else return true; } @Override public String toString() { // TODO Auto-generated method stub return "Circle:"; } } class Rectangle extends Shape { private double width; private double length; Rectangle() { } public Rectangle(double width, double length) { super(); this.width = width; this.length = length; } 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() { // TODO Auto-generated method stub return width * length; } @Override public boolean validate() { // TODO Auto-generated method stub if (width < 0 | length < 0) return false; else return true; } @Override public String toString() { // TODO Auto-generated method stub return "Rectangle:"; } } class Triangle extends Shape { private double side1; private double side2; private double side3; Triangle() { } public Triangle(double side1, double side2, double side3) { super(); this.side1 = side1; this.side2 = side2; this.side3 = side3; } public double getSide1() { return side1; } public void setSide1(double side1) { this.side1 = side1; } public double getSide2() { return side2; } public void setSide2(double side2) { this.side2 = side2; } public double getSide3() { return side3; } public void setSide3(double side3) { this.side3 = side3; } @Override public double getArea() { // TODO Auto-generated method stub double i = (side1 + side2 + side3) / 2.0; return Math.sqrt(i * (i - side1) * (i - side2) * (i - side3)); } @Override public boolean validate() { // TODO Auto-generated method stub double[] side = { side1, side2, side3 }; Arrays.sort(side); if (side1 <= 0 | side2 <= 0 | side3 <= 0 | side[0] + side[1] <= side[2] | side[2] - side[1] >= side[0]) return false; else return true; } @Override public String toString() { // TODO Auto-generated method stub return "Triangle:"; } } class Trapezoid extends Shape { double topSide; double bottomSide; double height; Trapezoid() { } public Trapezoid(double topSide, double bottomSide, double height) { super(); this.topSide = topSide; this.bottomSide = bottomSide; this.height = height; } public double getTopSide() { return topSide; } public void setTopSide(double topSide) { this.topSide = topSide; } public double getBottomSide() { return bottomSide; } public void setBottomSide(double bottomSide) { this.bottomSide = bottomSide; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } @Override public double getArea() { // TODO Auto-generated method stub return (topSide + bottomSide) * height / 2.0; } @Override public boolean validate() { // TODO Auto-generated method stub if (topSide < 0 | bottomSide < 0 | height < 0) return false; else return true; } @Override public String toString() { // TODO Auto-generated method stub return "Trapezoid:"; } }
创建好各类后,在主函数中创建一个对象数组,将所输入的图形数据等都放入图形数组中,便于在后续的使用:
ArrayList<Shape> shape = new ArrayList<>();
for (int i = 0; i < list.size(); i++) { if (list.get(i) == 1) { double radius = in.nextDouble(); Shape circle = new Circle(radius); shape.add(circle); } if (list.get(i) == 2) { double width = in.nextDouble(); double length = in.nextDouble(); Shape rectangle = new Rectangle(width, length); shape.add(rectangle); } if (list.get(i) == 3) { double side1 = in.nextDouble(); double side2 = in.nextDouble(); double side3 = in.nextDouble(); Shape triangle = new Triangle(side1, side2, side3); shape.add(triangle); } if (list.get(i) == 4) { double topSide = in.nextDouble(); double bottomSide = in.nextDouble(); double height = in.nextDouble(); Shape trapezoid = new Trapezoid(topSide, bottomSide, height); shape.add(trapezoid); } }
(2)题目集七(7-2)
类图及复杂分析图如下:
在7-2中,沿袭作业 7-1,本次作业主要对卡片(Card)进行分组游戏,其规则为随机发放一些卡片给学生, 卡片仍然分为四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid), 并给出各种卡片的相应参数,要求学生首先根据卡片类型将所有卡片进行分组(一个类型分为一组, 所以最多四组),然后能够对每组内的卡片根据面积值从大到小进行排序,同时求出该组内所有卡片 的面积之和,最后求出每组卡片面积之和中的最大值。
该题与7-1不同的是,7-2中需要首先根据卡片类型将所有卡片进行分组,然后分别将这四种图形存入四个ArrayList()数组列表中,然后将输入的图形放入到各自相对应的数组列表中,然后再通过对各个列表的面积进行排序和求总面积,这样就能求出每组卡片的面积值的排序和该组内所有卡片面积之和以及相对应的组中的面积之和的最大值。其他类中大部分都没有改动。
创建四个图形的对象数组,将输入的图形数据按照不同的图形放入不同的对象数组中去:
ArrayList<Shape> shape = new ArrayList<>(); ArrayList<Circle> circle1 = new ArrayList<>(); ArrayList<Rectangle> rectangle1 = new ArrayList<>(); ArrayList<Triangle> triangle1 = new ArrayList<>(); ArrayList<Trapezoid> trapezoid1 = new ArrayList<>(); if(num==0) { System.out.println("Wrong Format"); System.exit(0); } while (num != 0) { if (num < 0 || num > 4) { System.out.println("Wrong Format"); System.exit(0); } list.add(num); num = in.nextInt(); } for (int i = 0; i < list.size(); i++) { if (list.get(i) == 1) { double radius = in.nextDouble(); Shape circle = new Circle(radius); shape.add(circle); circle1.add((Circle) circle); } if (list.get(i) == 2) { double width = in.nextDouble(); double length = in.nextDouble(); Shape rectangle = new Rectangle(width, length); shape.add(rectangle); rectangle1.add((Rectangle) rectangle); } if (list.get(i) == 3) { double side1 = in.nextDouble(); double side2 = in.nextDouble(); double side3 = in.nextDouble(); Shape triangle = new Triangle(side1, side2, side3); shape.add(triangle); triangle1.add((Triangle) triangle); } if (list.get(i) == 4) { double topSide = in.nextDouble(); double bottomSide = in.nextDouble(); double height = in.nextDouble(); Shape trapezoid = new Trapezoid(topSide, bottomSide, height); shape.add(trapezoid); trapezoid1.add((Trapezoid) trapezoid); } } for (int i = 0; i < shape.size(); i++) { if (shape.get(i).validate() == false) { System.out.println("Wrong Format"); System.exit(0); } }
比较方法使用Compare方法:
//打印圆 System.out.println("The Separated sorted List:"); System.out.print("["); circle1.stream().sorted((u1,u2)->{return Double.compare(u2.getArea(),u1.getArea());}) .forEach(u1->{System.out.printf("Circle:%.2f ", u1.getArea());}); System.out.print("]"); //打印矩形 System.out.print("["); rectangle1.stream().sorted((u1,u2)->{return Double.compare(u2.getArea(),u1.getArea());}) .forEach(u1->{System.out.printf("Rectangle:%.2f ", u1.getArea());}); System.out.print("]"); //打印三角形 System.out.print("["); triangle1.stream().sorted((u1,u2)->{return Double.compare(u2.getArea(),u1.getArea());}) .forEach(u1->{System.out.printf("Triangle:%.2f ", u1.getArea());}); System.out.print("]"); //打印梯形 System.out.print("["); trapezoid1.stream().sorted((u1,u2)->{return Double.compare(u2.getArea(),u1.getArea());}) .forEach(u1->{System.out.printf("Trapezoid:%.2f ", u1.getArea());}); System.out.print("]");
(3)习题八
复杂分析图如下:
习题八为编写一个银行 ATM 机的模拟程序,能够完成用户的存款、取款以及查询余额功能。尝试使用面向对象技术对银行用户在 ATM 机上进行相关操作的模拟系统设 计,上述的相关概念均要设计为实体类,业务(控制)类请自行根据实际需要进 行扩充和完善。本次作业限定银行卡均为借记卡(不能透支),且不允许跨行办理相关业务(例如在中国建设银行的 ATM 机上对其他银行的账户进行操作。
初始化数据:将所给的数据都分别存放入不同的数组中
static String[] CardNum = { "6217000010041315709", "6217000010041315715", "6217000010041315718", "6217000010051320007", "6222081502001312389", "6222081502001312390", "6222081502001312399", "6222081502001312400", "6222081502051320785", "6222081502051320786" }; static String[] BankNum = { "中国建设银行", "中国建设银行", "中国建设银行", "中国建设银行", "中国工商银行", "中国工商银行", "中国工商银行", "中国工商银行", "中国工商银行", "中国工商银行" }; static String[] AtmNum = { "01", "02", "03", "04", "05", "06" }; static String[] name = { "杨过", "杨过", "杨过", "郭靖", "张无忌", "张无忌", "张无忌", "张无忌", "韦小宝", "韦小宝" }; static String[] AccountNum = { "3217000010041315709", "3217000010041315709", "3217000010041315715", "3217000010051320007", "3222081502001312389", "3222081502001312390", "3222081502001312399", "3222081502001312399", "3222081502051320785", "3222081502051320785" };
使用HashMap进行储存数据和HashSet实现set集合
HashMap<String,Account> map = new HashMap<>(); Set<String> set = new HashSet<>(); Account lastAccount=null; for(int i=0;i<name.length;i++) { if(set.contains(AccountNum[i])) map.put(CardNum[i], lastAccount); else { Account account = new Account(BankNum[i],AccountNum[i],name[i],10000.00); map.put(CardNum[i], account); set.add(AccountNum[i]); lastAccount=account; } }
创建各银行,账户,用户类等,然后进行一一对比判断。
(4)习题九
类图及复杂分析图如下:
编写一个银行 ATM 机的模拟程序,能够完成用户的取款以及查询余额功能。尝试使用面向对象技术对银行用户在 ATM 机上进行相关操作的模拟系统设计,上述的相关概念均要设计为实体类,业务(控制)类请自行根据实际需要进 行扩充和完善。本次作业中银行卡包含借记卡和信用卡两类,且允许跨行办理相关业 务(例如在中国建设银行的 ATM 机上使用中国工商银行的银行卡进行业务操作)。
通过上一次作业中老师的讲解,有了更清晰的思路,本题与上一题的区别是增加了更多功能,增加了贷记卡即可超额借款,可以跨账户转账,但需要考虑手续费,利息和超额借款的限度等,对于本题先是初始化数据,然后对各个类中的数据进行一一嵌套,然后判断是什么卡,是否跨行,是否超过了借款限度,手续费和利息等等;
在一开始我不懂得怎么初始化数据,尤其是如何让一个数据里面可以有另一个数据的信息,然后经过老师对代码的讲解就明白了,可以在创建对象对他初始化,相比于上一次代码,在初始化数据时需要增加银行,账户,用户等,同时可以在初始化Bank时就将每个银行所对应的利率加入进去,同时在初始化Card时,增加每张卡的属性是借记卡还是贷记卡,在后面判断卡时更好操作;在了解设计的背景后知道有哪些实体类要设计并且要知道比如账号,密码等信息究竟是属于那个类的属性,然后设计了UnionPay、Bank、ATM、User、Account、Card这些类,并且各个有关系的类之间用ArrayList连接在一起 2.业务类:拿老师的例子来说有GetBalance、ValidateData、Withdraw来实现余额的查询,存、取钱等功能。
UnionPay unionPay = new UnionPay(); Bank ccb = new Bank("1001","中国建设银行",0.02); Bank icbc = new Bank("1002","中国工商银行",0.03); Bank nc = new Bank("1003","中国农业银行",0.04); unionPay.addBank(ccb); unionPay.addBank(icbc); unionPay.addBank(nc); ATM aTM1 = new ATM("01",ccb); ATM aTM2 = new ATM("02",ccb); ATM aTM3 = new ATM("03",ccb); ATM aTM4 = new ATM("04",ccb); ATM aTM5 = new ATM("05",icbc); ATM aTM6 = new ATM("06",icbc); ATM aTM7 = new ATM("07",nc); ATM aTM8 = new ATM("08",nc); ATM aTM9 = new ATM("09",nc); ATM aTM10 = new ATM("10",nc); ATM aTM11 = new ATM("11",nc); ccb.addATM(aTM1); ccb.addATM(aTM2); ccb.addATM(aTM3); ccb.addATM(aTM4); icbc.addATM(aTM5); icbc.addATM(aTM6); nc.addATM(aTM7); nc.addATM(aTM8); nc.addATM(aTM9); nc.addATM(aTM10); nc.addATM(aTM11); User Yangguo = new User("360101200102122324","杨过"); User Guojing = new User("360101200012302552","郭靖"); User Zhangwuji = new User("360502199805163221","张无忌"); User Weixiaobao = new User("360201200513243326","韦小宝"); User zhangsanfeng = new User("3640000010045442002","张三丰"); User linghuchong = new User("3640000010045441009","令狐冲"); User qiaofeng = new User("3630000010033431001 ","乔峰"); User hongqigong = new User("3630000010033431008","洪七公"); Account ccbAcc1 = new Account("3217000010041315709",10000.00,Yangguo,ccb); Account ccbAcc2 = new Account("3217000010041315715",10000.00,Yangguo,ccb); Account ccbAcc3 = new Account("3217000010051320007",10000.00,Guojing,ccb); Account ccbAcc4 = new Account("3640000010045442002",10000.00,zhangsanfeng,ccb); Account icbcAcc1 = new Account("3222081502001312389",10000.00,Zhangwuji,icbc); Account icbcAcc2 = new Account("3222081502001312390",10000.00,Zhangwuji,icbc); Account icbcAcc3 = new Account("3222081502001312399",10000.00,Zhangwuji,icbc); Account icbcAcc4 = new Account("3222081502051320785",10000.00,Weixiaobao,icbc); Account icbcAcc5 = new Account("3222081502051320786",10000.00,Weixiaobao,icbc); Account icbcAcc6 = new Account("3640000010045441009",10000.00,linghuchong,icbc); Account ncAcc1 = new Account("3630000010033431001",10000.00,qiaofeng,nc); Account ncAcc2 = new Account("3630000010033431008",10000.00,hongqigong,nc); ccb.addAccount(ccbAcc1); ccb.addAccount(ccbAcc2); ccb.addAccount(ccbAcc3); ccb.addAccount(ccbAcc4); icbc.addAccount(icbcAcc1); icbc.addAccount(icbcAcc2); icbc.addAccount(icbcAcc3); icbc.addAccount(icbcAcc4); icbc.addAccount(icbcAcc5); nc.addAccount(ncAcc1); nc.addAccount(ncAcc2); Yangguo.addAccount(ccbAcc1); Yangguo.addAccount(ccbAcc2); Guojing.addAccount(ccbAcc3); zhangsanfeng.addAccount(ccbAcc4); Zhangwuji.addAccount(icbcAcc1); Zhangwuji.addAccount(icbcAcc2); Zhangwuji.addAccount(icbcAcc3); Weixiaobao.addAccount(icbcAcc4); linghuchong.addAccount(icbcAcc5); qiaofeng.addAccount(ncAcc1); hongqigong.addAccount(ncAcc2); Card ccbCard1 = new Card("6217000010041315709","88888888",ccbAcc1,"借记账号"); Card ccbCard2 = new Card("6217000010041315715","88888888",ccbAcc1,"借记账号"); Card ccbCard3 = new Card("6217000010041315718","88888888",ccbAcc2,"借记账号"); Card ccbCard4 = new Card("6217000010051320007","88888888",ccbAcc3,"借记账号"); Card icbcCard5 = new Card("6222081502001312389","88888888",icbcAcc1,"借记账号"); Card icbcCard6 = new Card("6222081502001312390","88888888",icbcAcc2,"借记账号"); Card icbcCard7 = new Card("6222081502001312399","88888888",icbcAcc3,"借记账号"); Card icbcCard8 = new Card("6222081502001312400","88888888",icbcAcc3,"借记账号"); Card icbcCard9 = new Card("6222081502051320785","88888888",icbcAcc4,"借记账号"); Card icbcCard10 = new Card("6222081502051320786","88888888",icbcAcc4,"借记账号"); Card ccbCard11 = new Card("6640000010045442002","88888888",ccbAcc4,"贷记账号"); Card ccbCard12 = new Card("6640000010045442003","88888888",ccbAcc4,"贷记账号"); Card icbcCard13 = new Card("6640000010045441009","88888888",icbcAcc5,"贷记账号"); Card ncCard14 = new Card("6630000010033431001","88888888",ncAcc1,"贷记账号"); Card ncCard15 = new Card("6630000010033431008","88888888",ncAcc2,"贷记账号"); ccbAcc1.addCard(ccbCard1); ccbAcc1.addCard(ccbCard2); ccbAcc2.addCard(ccbCard3); ccbAcc3.addCard(ccbCard4); icbcAcc1.addCard(icbcCard5); icbcAcc2.addCard(icbcCard6); icbcAcc3.addCard(icbcCard7); icbcAcc3.addCard(icbcCard8); icbcAcc4.addCard(icbcCard9); icbcAcc5.addCard(icbcCard10); ccbAcc4.addCard(ccbCard11); ccbAcc4.addCard(ccbCard12); icbcAcc6.addCard(icbcCard13); ncAcc1.addCard(ncCard14); ncAcc2.addCard(ncCard15);
在Withdraw类中对所有情况进行考虑和判断
public class Withdraw { private UnionPay unionPay; private String cardNO; private String cardPassword; private String ATMID; private double amount; private String type; public Withdraw() { super(); // TODO Auto-generated constructor stub } public Withdraw(UnionPay unionPay,String cardNO, String cardPassword, String aTMID, double amount) { super(); this.unionPay = unionPay; this.cardNO = cardNO; this.cardPassword = cardPassword; ATMID = aTMID; this.amount = amount; } public Withdraw(String cardNO, String cardPassword, String aTMID, double amount, String type) { super(); this.cardNO = cardNO; this.cardPassword = cardPassword; ATMID = aTMID; this.amount = amount; this.type = type; } public void withdraw() { /** * 校验该卡是否存在 */ Card card = ValidateData.getCardbyCardNO(unionPay, cardNO); if (card == null) { System.out.println("Sorry,this card does not exist."); System.exit(0); } /** * 校验ATM是否存在 */ ATM aTM = ValidateData.getATMbyATMID(unionPay, ATMID); if (aTM == null) { System.out.println("Sorry,the ATM's id is wrong."); System.exit(0); } Account account = Account.getAmountbyCardNO(cardNO); double balance = account.getBalance(); /** * 校验卡密码是否正确 */ if (!card.getCardPassword().equals(cardPassword)) { System.out.println("Sorry,your password is wrong."); System.exit(0); } double rate1=0.05; //跨行取款 if(account.getBank().getBankNO() != aTM.getBank().getBankNO()) { if(card.getType().equals("贷记账号")) { //不透支 if(balance-amount>0) balance=balance - ValidateData.getBankbyATMID(unionPay, ATMID).getRate()*amount; //透支 else { if(balance-amount<-50000) { System.out.println("Sorry,your account balance is insufficient."); System.exit(0); } if(balance>0) balance=balance-ValidateData.getBankbyATMID(unionPay, ATMID).getRate()*amount-(amount-balance)*rate1; else balance=balance-ValidateData.getBankbyATMID(unionPay, ATMID).getRate()*amount-amount*rate1; //透支取款后判断是否还能透支 } } if(card.getType().equals("借记账号")) { //正常取款 balance=balance - ValidateData.getBankbyATMID(unionPay, ATMID).getRate()*amount; //超额取款 }if(balance<amount) { System.out.println("Sorry,your account balance is insufficient."); System.exit(0); } } //不跨行 else { if(card.getType().equals("借记账号")) { balance=balance; } if(card.getType().equals("贷记账号")) { //不透支 if(balance-amount>0) balance=balance; //透支 else { if(balance>0) balance=balance-(amount-balance)*rate1; else balance=balance-amount*rate1; //透支取款后判断是否还能透支 if(balance-amount<-50000) { System.out.println("Sorry,your account balance is insufficient."); System.exit(0); } } } } //更新余额 account.setBalance(balance - amount); if (amount >= 0) { showResult(account, "Y"); } else { showResult(account, "N"); } } //跨行取款 public void showResult(Account account, String flag1) { Card card = ValidateData.getCardbyCardNO(unionPay, cardNO); String type1 = ""; if (flag1 == "Y") { type1 = "取款"; } if (flag1 == "N") { type1 = "存款"; amount *= -1; } String userName = account.getUser().getName(); //String bankName = account.getBank().getBankName(); System.out.println("业务:" + type1 + " " + userName + "在" + ValidateData.getBankbyATMID(unionPay, ATMID).getBankName() + "的" + ATMID + "号ATM机上" + type1 + String.format("¥%.2f", amount)); System.out.println("当前余额为" + String.format("¥%.2f", account.getBalance())); } }
为通过卡号获取该账户所在的银行,ATM机,ATM机编号创建了一个ValidateData类,首先先通过迭代器进行遍历校对卡号,然后在对需要判断的再次进行迭代遍历判断
public class ValidateData { public static Card getCardbyCardNO(UnionPay unionPay,String cardNO) { Card card = null; Iterator<Bank> bankItr = unionPay.getBankList().iterator(); while(bankItr.hasNext()) { // ArrayList<Account> accountList = bankItr.next().getAccountList(); Iterator<Account> accountItr = accountList.iterator(); while(accountItr.hasNext()) { ArrayList<Card> cardList = accountItr.next().getList(); Iterator<Card> cardItr = cardList.iterator(); while(cardItr.hasNext()) { card = cardItr.next(); // if(card.getCardNO().equals(cardNO)) { return card; } } } } return null; } /** * 校验ATM ID是否存在 * @param unionPay * @param ATMID * @return */ public static ATM getATMbyATMID(UnionPay unionPay,String ATMID) { 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; } } } return null; } public static Bank getBankbyATMID(UnionPay unionPay,String ATMID) { 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.getBank(); } } } return null; } }
题目集8用于设计一个简单的ATM机功能,功能作用在:简单的存取款与查询余额。设计的背景为:中国银联,中国银行,银行用户,银行账户,银行卡,ATM机。各个组成部分,都可以实现为一个实体类。各个实体类之间有一定的关联性。
对于题目集9,功能更全面复杂,如:能够完成用户的取款以及查询余额功能。银行账户分为借记账户和贷记账户两种,其中,借记账户不能够透支 取款,而贷记账户可以透支取款(可能需要支付手续费)。且允许跨行办理相关业 务。考察的依旧是:继承,多态,抽象类,类间关系设计以及对于“开-闭”原则,单一职责原则的掌握。
跟题目集8的7-1有所不同的是添加一种信用卡,可以进行贷记操作,以及银联有了超额度的服务费扣取功能,跨行收费。主类中都是根据正则表达式以及if语句决定功能走向的分支。不同点在于会在题目集9的代码中不同的银行添加不同的利率属性,在业务类中添加对跨行后的收费处理以及透支判断等。以上都是对特定功能的添加,需要考虑到类设计的“开-闭”原则,单一职责原则。以及迭代到的不仅是相同背景内容的功能添加,更有考虑到类间关系,去充分利用实体类的属性绑定以及方法调用。业务类中集成方法去实现最终输出的效果。本次ATM机迭代编程,本身逻辑层面简单,注重的是严谨的设计思想与正确的面向对象编程思维。
二、踩坑心得
1:在习题七的7-2中,因为我将不同的图形放置于不同的对象数组导致如果我要使用CompareTo的话就会比较麻烦,需要每一个类中都再增加此方法,为了更加简洁在同学的帮助下学会了lamba表达式,简洁有效,其次如果我开始将四种图形放在同一个对象数组中再使用CompareTo可能不会走这么多弯路;
circle1.sort((u1,u2)->{return Double.compare(u1.getArea(), u2.getArea());}); rectangle1.sort((u1,u2)->{return Double.compare(u1.getArea(), u2.getArea());}); triangle1.sort((u1,u2)->{return Double.compare(u1.getArea(), u2.getArea());}); trapezoid1.sort((u1,u2)->{return Double.compare(u1.getArea(), u2.getArea());});
2:在7-2提交时因代码长度过长无法提交代码,代码较累赘,后为了提交只得删减空行,删减注释,以及将可放在一行的代码尽量放在一行内等,这样的话虽然能够通过了,但是在视觉上看起来还是有点不太美观,因此以后写代码时还是应该多思考怎么能更简洁,高效一些;
3:在习题九中,对于借贷时没有注意他只是超过了的那部分才需要乘以利息导致开始时的数据总是错误,后注意到后修改了计算方法;
4:超过了额度的钱才可以被取出,所写的判断没有起到作用,同时当跨行取出全部金额时,因为要扣除跨行费用本应该不能取出,但是他却可以继续取,后发现所写的顺序有点混乱后重新写了跨行和超额取款部分
//跨行取款 if(account.getBank().getBankNO() != aTM.getBank().getBankNO()) { if(card.getType().equals("贷记账号")) { //不透支 if(balance-amount>0) balance=balance - ValidateData.getBankbyATMID(unionPay, ATMID).getRate()*amount; //透支 else { if(balance-amount<-50000) { System.out.println("Sorry,your account balance is insufficient."); System.exit(0); } if(balance>0) balance=balance-ValidateData.getBankbyATMID(unionPay, ATMID).getRate()*amount-(amount-balance)*rate1; else balance=balance-ValidateData.getBankbyATMID(unionPay, ATMID).getRate()*amount-amount*rate1; //透支取款后判断是否还能透支 } } if(card.getType().equals("借记账号")) { //正常取款 balance=balance - ValidateData.getBankbyATMID(unionPay, ATMID).getRate()*amount; //超额取款 }if(balance<amount) { System.out.println("Sorry,your account balance is insufficient."); System.exit(0); } }
二、改进建议
在习题七和八中对于输出都写的很复杂,基本同样的代码重复写了四遍,太过重复,可以单独写一个方法来写输出代码,减少重复;同时应该充分提高代码的复用性,并且尽可能提升代码的安全性,并做好封装,此外如果业务类要实现的功能很多,应该尽可能细化,实现单一性原则和开闭原则。
二、总结
通过本阶段的学习,总体来说锻炼的就是在设计的时候还要考虑多种类的特性,开闭原则和单一性原则,然后就是作业虽然有难度但是学到的东西也很多,比如通过这次ATM机的类设计,慢慢的贴近现实生活,在类设计之前也会考虑很多现实生活中的问题,感觉学习编程更有意思了一些,但通过这几次游戏和ATM机的设计也让我体会到了编程的难度,我还需要继续学习多多学习。