#OO第三阶段学习总结
OO第三阶段学习总结
前言:
设计与分析:
①
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:面积值。
类图:
点击查看代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
sout app=new sout();
Scanner sc = new Scanner(System.in);
ArrayList<Comp> s = new ArrayList<>();
ArrayList<Integer> l = new ArrayList<>();
int key = sc.nextInt();
if(key==0){
app.out("Wrong Format");
System.exit(0);
}
while (key != app.fals(0)) {
if (key > app.fals(4) || key < app.fals(1)) {
app.out("Wrong Format");
System.exit(app.ture()-1);
}
l.add(key);
key = sc.nextInt();
}
for (int i = app.fals(0); i < l.size(); i++) {
if (l.get(i) == app.ture()) {
double r = sc.nextDouble();
Shape shape = new Circle(r);
Comp comp = new Comp(shape);
comp.shape.setShapeName("Circle");
s.add(comp);
}
if (l.get(i) == app.fals(2)) {
double width = sc.nextDouble();
double length = sc.nextDouble();
Shape shape = new Rectangle(length, width);
Comp comp = new Comp(shape);
comp.shape.setShapeName("Rectangle");
s.add(comp);
}
if (l.get(i) == app.fals(3)) {
double x = sc.nextDouble();
double y = sc.nextDouble();
double z = sc.nextDouble();
Shape shape = new Triangle(x, y, z);
Comp comp = new Comp(shape);
comp.shape.setShapeName("Triangle");
s.add(comp);
}
if (l.get(i) == app.fals(4)) {
double x = sc.nextDouble();
double y = sc.nextDouble();
double z = sc.nextDouble();
Shape shape = new Trapezoid(x, y, z);
Comp comp = new Comp(shape);
comp.shape.setShapeName("Trapezoid");
s.add(comp);
}
}
double sum1=0,sum2=0,sum3=0,sum4=0;
if(check(s)){
app.outln("The original list:");
System.out.print("[");
for (Comp comp : s) {
System.out.print(comp.shape.getShapeName() + ":" + String.format("%.2f", comp.shape.getArea()) + " ");
}
System.out.print("]");
System.out.println("\nThe Separated List:");
System.out.print("[");
for (int i= app.fals(0);i<s.size();i++){
if(s.get(i).shape.getShapeName().equals("Circle")){
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
sum1+=s.get(i).shape.getArea();
}
}
System.out.print("]");
System.out.print("[");
for (int i= app.fals(0);i<s.size();i++){
if(s.get(i).shape.getShapeName().equals("Rectangle")){
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
sum2+=s.get(i).shape.getArea();
}
}
System.out.print("]");
System.out.print("[");
for (int i= app.fals(0);i<s.size();i++){
if(s.get(i).shape.getShapeName().equals("Triangle")){
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
sum3+=s.get(i).shape.getArea();
}
}
System.out.print("]");
System.out.print("[");
for (int i= app.fals(0);i<s.size();i++){
if(s.get(i).shape.getShapeName().equals("Trapezoid")){
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
sum4+=s.get(i).shape.getArea();
}
}
System.out.print("]");
app.outln("\nThe Separated sorted List:");
s.sort(Collections.reverseOrder());
System.out.print("[");
for (int i= app.fals(0);i<s.size();i++){
if(s.get(i).shape.getShapeName().equals("Circle")){
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
}
}
System.out.print("]");
System.out.print("[");
for (int i= app.fals(0);i<s.size();i++){
if(s.get(i).shape.getShapeName().equals("Rectangle")){
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
}
}
System.out.print("]");
System.out.print("[");
for (int i= app.fals(0);i<s.size();i++){
if(s.get(i).shape.getShapeName().equals("Triangle")){
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
}
}
System.out.print("]");
System.out.print("[");
for (int i= app.fals(0);i<s.size();i++){
if(s.get(i).shape.getShapeName().equals("Trapezoid")){
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
}
}
System.out.print("]");
double max=0;
if(max<sum1)
max=sum1;
if(max<sum2)
max=sum2;
if(max<sum3)
max=sum3;
if(max<sum4)
max=sum4;
app.out("\nThe max area:"+String.format("%.2f",max));
}
else
{
app.out("Wrong Format");
}
}
public static boolean check(ArrayList<Comp> s){
for (Comp comp : s) {
if (!comp.shape.vaildate())
return false;
}
return true;
}
}
class Circle extends Shape {
double radius;
Circle(double r) {
radius = r;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public boolean vaildate() {
return radius > 0;
}
}
class Rectangle extends Shape {
double width;
double length;
Rectangle(double l, double w) {
width = w;
length = l;
}
@Override
public double getArea() {
return width * length;
}
@Override
public boolean vaildate() {
return (length > 0 && width > 0);
}
}
abstract class Shape {
private String shapeName;
public void setShapeName(String shapeName) {
this.shapeName = shapeName;
}
public String getShapeName() {
return shapeName;
}
public abstract double getArea();
public abstract boolean vaildate();
}
class Triangle extends Shape {
sout a=new sout();
double side1, side2, side3;
Triangle(double s1, double s2, double s3) {
side2 = s2;
side1 = s1;
side3 = s3;
}
@Override
public double getArea() {
double s = (side1 + side2 + side3) /(a.ture()+1);
return Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
@Override
public boolean vaildate() {
if (side1 < a.fals(0) || side3 < a.fals(0) || side2 < 0) {
return false;
}
double[] q = new double[3];
q[0] = side1;
q[1] = side2;
q[2] = side3;
Arrays.sort(q);
return q[0] + q[1] > q[2];
}
}
class Trapezoid extends Shape {
sout app=new sout();
double a;
double b;
double c;
Trapezoid(double a, double b, double c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public boolean vaildate() {
return a > app.ture() - 1 && b > 0 && c > 0;
}
public double getArea() {
double s;
s = (a + b) * c / app.fals(2);
return s;
}
}
class Comp implements Comparable<Comp> {
sout app=new sout();
Shape shape;
Comp(Shape shape) {
this.shape = shape;
}
@Override
public int compareTo(Comp o) {
if (this.shape.getArea() >= o.shape.getArea()) {
return app.ture();
} else
return -app.ture();
}
}
class sout {
final int num = 1;
public void outln(String a) {
int b = 6;
int c = 5;
int d;
d = 6 + 5 * b + c+num;
if(d==42)
System.out.println(a);
}
public void out(String a) {
int b = 6;
int c = 5;
int d;
d = 6 + 5 * b + c+num;
if(d==42)
System.out.print(a);
}
public int ture() {
int a = 4;
int b = 3;
return a - b;
}
public int fals(int a){
int d=4;
int s=d*num-3;
return s*a*ture();
}
}
②
7-1 图形卡片排序游戏 (40 分)
掌握类的继承、多态性使用方法以及接口的应用。详见作业指导书 2020-OO第07次作业-1指导书V1.0.pdf
输入格式:
首先,在一行上输入一串数字(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:总面积值。
类图:
代码分享
点击查看代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
sout app=new sout();
Scanner sc = new Scanner(System.in);
ArrayList<Comp> s = new ArrayList<>();
ArrayList<Integer> l = new ArrayList<>();
int key = sc.nextInt();
while (key != app.fals(0)) {
if (key > app.fals(4) || key < app.fals(1)) {
app.outln("Wrong Format");
System.exit(app.ture()-1);
}
l.add(key);
key = sc.nextInt();
}
for (int i = app.fals(0); i < l.size(); i++) {
if (l.get(i) == app.ture()) {
double r = sc.nextDouble();
Shape shape = new Circle(r);
Comp comp = new Comp(shape);
comp.shape.setShapeName("Circle");
s.add(comp);
}
if (l.get(i) == app.fals(2)) {
double width = sc.nextDouble();
double length = sc.nextDouble();
Shape shape = new Rectangle(length, width);
Comp comp = new Comp(shape);
comp.shape.setShapeName("Rectangle");
s.add(comp);
}
if (l.get(i) == app.fals(3)) {
double x = sc.nextDouble();
double y = sc.nextDouble();
double z = sc.nextDouble();
Shape shape = new Triangle(x, y, z);
Comp comp = new Comp(shape);
comp.shape.setShapeName("Triangle");
s.add(comp);
}
if (l.get(i) == app.fals(4)) {
double x = sc.nextDouble();
double y = sc.nextDouble();
double z = sc.nextDouble();
Shape shape = new Trapezoid(x, y, z);
Comp comp = new Comp(shape);
comp.shape.setShapeName("Trapezoid");
s.add(comp);
}
}
double sum=0;
if(check(s)){
app.outln("The original list:");
for (Comp comp : s) {
System.out.print(comp.shape.getShapeName() + ":" + String.format("%.2f", comp.shape.getArea()) + " ");
sum += comp.shape.getArea();
}
app.outln("\nThe sorted list:");
s.sort(Collections.reverseOrder());
for (int i= app.fals(0);i<s.size();i++)
{
System.out.print(s.get(i).shape.getShapeName()+":"+String.format("%.2f",s.get(i).shape.getArea())+" ");
}
app.outln("\nSum of area:"+String.format("%.2f",sum));
}
else
{
app.outln("Wrong Format");
}
}
public static boolean check(ArrayList<Comp> s){
for (Comp comp : s) {
if (!comp.shape.vaildate())
return false;
}
return true;
}
}
class Circle extends Shape {
double radius;
Circle(double r) {
radius = r;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public boolean vaildate() {
return radius > 0;
}
}
class Rectangle extends Shape {
double width;
double length;
Rectangle(double l, double w) {
width = w;
length = l;
}
@Override
public double getArea() {
return width * length;
}
@Override
public boolean vaildate() {
return (length > 0 && width > 0);
}
}
abstract class Shape {
private String shapeName;
public void setShapeName(String shapeName) {
this.shapeName = shapeName;
}
public String getShapeName() {
return shapeName;
}
public abstract double getArea();
public abstract boolean vaildate();
}
class Triangle extends Shape {
sout a=new sout();
double side1, side2, side3;
Triangle(double s1, double s2, double s3) {
side2 = s2;
side1 = s1;
side3 = s3;
}
@Override
public double getArea() {
double s = (side1 + side2 + side3) /(a.ture()+1);
return Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
@Override
public boolean vaildate() {
if (side1 < a.fals(0) || side3 < a.fals(0) || side2 < 0) {
return false;
}
double[] q = new double[3];
q[0] = side1;
q[1] = side2;
q[2] = side3;
Arrays.sort(q);
return q[0] + q[1] > q[2];
}
}
class Trapezoid extends Shape {
sout app=new sout();
double a;
double b;
double c;
Trapezoid(double a, double b, double c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public boolean vaildate() {
return a > app.ture() - 1 && b > 0 && c > 0;
}
public double getArea() {
double s;
s = (a + b) * c / app.fals(2);
return s;
}
}
class Comp implements Comparable<Comp> {
sout app=new sout();
Shape shape;
Comp(Shape shape) {
this.shape = shape;
}
@Override
public int compareTo(Comp o) {
if (this.shape.getArea() >= o.shape.getArea()) {
return app.ture();
} else
return -app.ture();
}
}
class sout {
final int num = 1;
public void outln(String a) {
int b = 6;
int c = 5;
int d;
d = 6 + 5 * b + c+num;
if(d==42)
System.out.println(a);
}
public int ture() {
int a = 4;
int b = 3;
return a - b;
}
public int fals(int a){
int d=4;
int s=d*num-3;
return s*a*ture();
}
}
可以看到,他还是非常简单的对于上一道题。
题目集7(7-1)和题目集7(7-2)的类图相差不大,其中Main类、Shape类、Rectangle类、Triangle类、Circle类、Trapezoid类完全一样,类的属性和方法都没有改变,主要差距在于DealCardList类中,不难发现,7-2的DealCardList类中属性更多,方法也多了(,从这两个题目的递进式设计可以充分体现代码的复用性,以及代码的可拓展性。从类的属性和方法上观察,可以发现每个类都有每个类的特定功能,比如getArea()方法,每个继承Shape类的子类都进行了重写,用以获得各自的面积,体现了设计的“单一职责”原则,一个类/接口只执行一个职责。忽略接口的变化,7-1到7-2的最大区别在于7-2的DealCardList类在7-1的基础上增加了属性和方法,这体现了设计的“开-闭”原则,对扩展开放,对修改关闭。
③
7-3 ATM机类结构设计(一) (100 分)
设计ATM仿真系统,具体要求参见作业说明。 OO作业8-1题目说明.pdf
输入格式:
每一行输入一次业务操作,可以输入多行,最终以字符#终止。具体每种业务操作输入格式如下:
存款、取款功能输入数据格式: 卡号 密码 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编号]上存款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
④查询余额业务输出
¥[金额]
金额保留两位小数。
类图构建:
在这里我的思路也很简单,就是只有一个账户去构建,在设计上实现"单一职责"原则,然后使用ArrayList将各个类进行连接,使两个类之间实现一对多的关系,完成类间关系的设计。关于数据的检测,设计了一个Check方法,在设计上又体现"单一职责"原则。
来看看代码吧:
代码分享:
点击查看代码
package com;
import java.util.ArrayList;
import java.util.Scanner;
class Main {
public static void main(String[] args) {
AccDemo atm=new AccDemo();
atm.play();
}
}
class AccDemo {
ArrayList<Acc> acc = new ArrayList<>();
public void setAcc() {
Acc acc1 = new Acc();
acc1.setIdName("杨过");
acc1.setBankName("中国建设银行");
acc1.setBankNum("3217000010041315709");
acc1.setBalance(10000);
acc1.setCardNum("6217000010041315709", "6217000010041315715");
acc.add(acc1);
Acc acc2 = new Acc();
acc2.setIdName("杨过");
acc2.setBankName("中国建设银行");
acc2.setBankNum("3217000010041315715");
acc2.setBalance(10000);
acc2.setCardNum("6217000010041315718", null);
acc.add(acc2);
Acc acc3 = new Acc();
acc3.setIdName("郭靖");
acc3.setBankName("中国建设银行");
acc3.setBankNum("3217000010051320007");
acc3.setBalance(10000);
acc3.setCardNum("6217000010051320007", null);
acc.add(acc3);
Acc acc4 = new Acc();
acc4.setIdName("张无忌");
acc4.setBankName("中国工商银行");
acc4.setBankNum("3222081502001312389");
acc4.setBalance(10000);
acc4.setCardNum("6222081502001312389", null);
acc.add(acc4);
Acc acc5 = new Acc();
acc5.setIdName("张无忌");
acc5.setBankName("中国工商银行");
acc5.setBankNum("3222081502001312390");
acc5.setBalance(10000);
acc5.setCardNum("6222081502001312390", null);
acc.add(acc5);
Acc acc6 = new Acc();
acc6.setIdName("张无忌");
acc6.setBankName("中国工商银行");
acc6.setBankNum("3222081502001312399");
acc6.setBalance(10000);
acc6.setCardNum("6222081502001312399", "6222081502001312400");
acc.add(acc6);
Acc acc7 = new Acc();
acc7.setIdName("韦小宝");
acc7.setBankName("中国工商银行");
acc7.setBankNum("3222081502051320785");
acc7.setBalance(10000);
acc7.setCardNum("6222081502051320785", null);
acc.add(acc7);
Acc acc8 = new Acc();
acc8.setIdName("韦小宝");
acc8.setBankName("中国工商银行");
acc8.setBankNum("3222081502051320786");
acc8.setBalance(10000);
acc8.setCardNum("6222081502051320786", null);
acc.add(acc8);
}
public void play() {
int a=0;
setAcc();
Scanner sc = new Scanner(System.in);
String op = sc.nextLine();
while (!op.equals("#")) {
String[] data = op.split("\\s+");
if (data.length == 1) {
int flag = 0;
for (int i = 0; i < acc.size(); i++) {
if (data[0].equals(acc.get(i).getCardNum1()) || data[0].equals(acc.get(i).getCardNum2())) {
if(a!=0)
System.out.println();
System.out.print("¥" + String.format("%.2f",acc.get(i).getBalance()));
flag = 1;
a=2;
}
}
if (flag == 0)
System.out.println("Sorry,this card does not exist.");
} else {
if (!check(data))
System.exit(0);
int i =find(data);
if(!acc.get(i).bankOpt(data[2])){
System.out.print("Sorry,cross-bank withdrawal is not supported.");
System.exit(0);
}
acc.get(i).sm(Double.parseDouble(data[3]));
if (a!=0)
System.out.println();
acc.get(i).show(data[2], Double.parseDouble(data[3]));
a=2;
}
op = sc.nextLine();
}
System.exit(0);
}
public boolean check(String data[]) {
int flag = 0;
for (int i = 0; i < acc.size(); i++) {
if (data[0].equals(acc.get(i).getCardNum1()) || data[0].equals(acc.get(i).getCardNum2())) {
flag = 1;
if (!data[1].equals("88888888")) {
System.out.println("Sorry,your password is wrong.");
return false;
}
if (!data[2].matches("^0[1-6]$")) {
System.out.println("Sorry,the ATM's id is wrong.");
return false;
}
if (Double.parseDouble(data[3]) > acc.get(i).getBalance()) {
System.out.println("Sorry,your account balance is insufficient.");
return false;
}
}
}
if (flag == 0) {
System.out.println("Sorry,this card does not exist.");
return false;
} else
return true;
}
public int find(String data[]) {
for (int i = 0; i < acc.size(); i++) {
if (data[0].equals(acc.get(i).getCardNum1()) || data[0].equals(acc.get(i).getCardNum2())) {
return i;
}
}
return -1;
}
}
class Acc {
private String idName;
private String bankName;
private String bankNum;
private double balance;
private String[] cardNum=new String[2];
public String cipher="88888888";
/*设置用户的名字*/
public void setIdName(String idName) {
this.idName = idName;
}
/*得到用户名字*/
public String getIdName() {
return idName;
}
/*设置银行名*/
public void setBankName(String bankName) {
this.bankName = bankName;
}
/*得到银行名*/
public String getBankName() {
return bankName;
}
/*设置银行账户*/
public void setBankNum(String bankNum) {
this.bankNum = bankNum;
}
/*得到银行账户*/
public String getBankNum() {
return bankNum;
}
/*设置余额*/
public void setBalance(double balance) {
this.balance = balance;
}
/*得到余额*/
public double getBalance() {
return balance;
}
/*设置银行卡号*/
public void setCardNum(String cardNum,String a) {
this.cardNum[0] = cardNum;
this.cardNum[1]=a;
}
/*得到银行卡号*/
public String getCardNum1() {
return cardNum[0];
}
public String getCardNum2() {
return cardNum[1];
}
public void sm(double money){
balance=balance-money;
}
public void show(String atm,double money){
if(money<0) {
System.out.println(getIdName() + "在" + getBankName()+"的"+atm+"号ATM机上存款¥" + String.format("%.2f",-money) );
System.out.print("当前余额为¥"+String.format("%.2f",getBalance()));
}
else if(money>=0){
System.out.println(getIdName()+"在"+getBankName()+"的"+atm+"号ATM机上取款¥"+String.format("%.2f",money));
System.out.print("当前余额为¥"+String.format("%.2f",getBalance()));
}
}
public boolean bankOpt(String atm){
if(getBankName().equals("中国建设银行")){
if(atm.equals("01")||atm.equals("02")||atm.equals("03")||atm.equals("04")){
return true;
}
else
return false;
}
if (getBankName().equals("中国工商银行")){
if(atm.equals("05")||atm.equals("06")){
return true;
}
else
return false;
}
return false;
}
}
④
设计ATM仿真系统,具体要求参见作业说明。 OO作业9-1题目说明.pdf
输入格式:
每一行输入一次业务操作,可以输入多行,最终以字符#终止。具体每种业务操作输入格式如下:
取款功能输入数据格式: 卡号 密码 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编号]上取款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
③查询余额业务输出
业务:查询余额 ¥[金额]
金额保留两位小数。
类图:
设计思路分析:此次题目是在老师给的题目集8的源码上进行重构设计的,在设计上可以发现Card类有个Account属性,这样的好处是可以根据卡号找到账户,实现了从小到大的查询。设计前对源码的部分代码进行了重构,比如检验数据的方法全部放在Data类中,使之符合单一职责原则。由于题目加了个可以跨行取款的操作,使账户有借记账户和贷记账户之分,卡有借记卡和信用卡之分,因此加了DebitAccount类、CreditAccount类、DebitCard类、CreditCard类,又由于这两个账户和这两个卡的属性和方法不需要重新再写,因此使这两个账户继承原来的Account类,这两种卡继承原来的Card类即可。不难发现,与题目集8的类图相比,在题目集8中我将这两个类放进了ATM类中使之成为方法使用,而在这单独拎出来作为一个类也是有可以的。
代码分析:
点击查看代码
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author:柠檬糖过留人山
* @data 2021/12/3 14:49
*/
public class Main{
meanless less=new meanless();
Scanner sc=new Scanner(System.in);
StringBuffer s=new StringBuffer();
String test1;
ArrayList<Bank> banks=new ArrayList<>();
public static void main(String[] args) {
Main test=new Main();
test.input();
test.format();
}
Main(){
banks.add(new Bank("中国建设银行"));
banks.add(new Bank("中国工商银行"));
banks.add(new Bank("中国农业银行"));
}
public void input(){
String a=sc.nextLine();
while(!a.equals("#")){
s.append(a).append("\n");
a=sc.nextLine();
}
test1=String.valueOf(s);
}
public void format(){
String[] tests=test1.split("\n");
for (int i=0;i<tests.length;i++)
{
int[] ids;
String s=tests[i].toString();
String[] a=s.split("[' ']+");
switch (a.length) {
case 1:
ids=findid(a[less.return0()]);
if(ids[less.return0()]==99){
System.out.println("Sorry,this card does not exist.");
System.exit(less.return0());
}
System.out.println("业务:查询余额 ¥"+
String.format("%.2f",banks.get(ids[less.return0()]).users.get(ids[1]).accounts.get(ids[2]).getmoney()));
break;
case 4:
String id=a[less.return0()];
String pass=a[less.return0()+1];
String at=a[less.return0()+2];
String money=a[less.return0()+3];
Double moneyx=Double.parseDouble(money);
ids=findid(a[less.return0()]);
if(ids[less.return0()]==99){
System.out.println("Sorry,this card does not exist.");
System.exit(less.return0());
}
atmvalidata(at);
int x=findatm(at);
passvalidate(pass);
if(banks.get(ids[0]).users.get(ids[1]).accounts.get(ids[2]).kind==true){
if(banks.get(ids[less.return0()]).name.equals(banks.get(x).name)){
banks.get(ids[less.return0()]).users.get(ids[1]).accounts.get(ids[2]).takemoney(moneyx);
System.out.println("业务:取款 "+banks.get(ids[0]).users.get(ids[1]).name+"在"+banks.get(x).name+"的"+at+"号ATM机上取款¥"
+String.format("%.2f",moneyx));
System.out.println("当前余额为¥"+String.format("%.2f",
banks.get(ids[0]).users.get(ids[1]).accounts.get(ids[2]).getmoney()));
}
else {
banks.get(ids[0]).users.get(ids[1]).accounts.get(ids[2]).takemoney(moneyx,banks.get(x).fee);
System.out.println("业务:取款 "+banks.get(ids[0]).users.get(ids[1]).name+"在"+banks.get(x).name+"的"+at+"号ATM机上取款¥"
+String.format("%.2f",moneyx));
System.out.println("当前余额为¥"+String.format("%.2f",
banks.get(ids[0]).users.get(ids[1]).accounts.get(ids[2]).getmoney()));
}
}
else {
if(banks.get(ids[less.return0()]).name.equals(banks.get(x).name)){
banks.get(ids[0]).users.get(ids[1]).accounts.get(ids[2]).takemoney(moneyx);
System.out.println("业务:取款 "+banks.get(ids[0]).users.get(ids[1]).name+"在"+banks.get(x).name+"的"+at+"号ATM机上取款¥"
+String.format("%.2f",moneyx));
System.out.println("当前余额为¥"+String.format("%.2f",
banks.get(ids[less.return0()]).users.get(ids[1]).accounts.get(ids[2]).getmoney()));
}
else {
banks.get(ids[0]).users.get(ids[1]).accounts.get(ids[2]).takemoney(moneyx,banks.get(x).fee);
System.out.println("业务:取款 "+banks.get(ids[0]).users.get(ids[1]).name+"在"+banks.get(x).name+"的"+at+"号ATM机上取款¥"
+String.format("%.2f",moneyx));
System.out.println("当前余额为¥"+String.format("%.2f",
banks.get(ids[0]).users.get(ids[1]).accounts.get(ids[2]).getmoney()));
}
}
break;
default:
break;
}
}
}
public int findatm(String atm){
for(int i= less.return0();i<banks.size();i++){
for(int j=0;j<banks.get(i).atms.size();j++){
if(banks.get(i).atms.get(j).serialNumber.equals(atm)){
return i;
}
}
}
return 0;
}
public void passvalidate(String pass){
if(!pass.equals("88888888")){
System.out.println("Sorry,your password is wrong.");
System.exit(0);
}
}
public void atmvalidata(String at){
if(!at.matches("0[1-9]|1[0-1]")){
System.out.println("Sorry,the ATM's id is wrong.");
System.exit(less.return0());
}
}
public int[] findid(String id){
int[] ids=new int[]{99,99,99,99};
for(int i=0;i<banks.size();i++){
for(int j=0;j<banks.get(i).users.size();j++){
for(int k=0;k<banks.get(i).users.get(j).accounts.size();k++){
for(int l=0;l<banks.get(i).users.get(j).accounts.get(k).cards.size();l++){
if(banks.get(i).users.get(j).accounts.get(k).cards.get(l).id.equals(id)){
ids[0]=i;
ids[1]=j;
ids[2]=k;
ids[3]=l;
return ids;
}
}
}
}
}
return ids;
}
}
class Bank{
String name;
ArrayList<ATM> atms=new ArrayList<>();
ArrayList<User> users=new ArrayList<>();
double fee;
double tofee=0.05;
Bank(String name){
this.name=name;
if(this.name.equals("中国建设银行")){
atms.add(new ATM("01"));
atms.add(new ATM("02"));
atms.add(new ATM("03"));
atms.add(new ATM("04"));
users.add(new User("杨过"));
users.add(new User("郭靖"));
users.add(new User("张三丰"));
fee=0.02;
}
if(this.name.equals("中国工商银行")){
atms.add(new ATM("05"));
atms.add(new ATM("06"));
users.add(new User("张无忌"));
users.add(new User("韦小宝"));
users.add(new User("令狐冲"));
fee=0.03;
}
if(this.name.equals("中国农业银行")){
atms.add(new ATM("07"));
atms.add(new ATM("08"));
atms.add(new ATM("09"));
atms.add(new ATM("10"));
atms.add(new ATM("11"));
users.add(new User("乔峰"));
users.add(new User("洪七公"));
fee=0.04;
}
}
}
class User{
ArrayList<Account> accounts=new ArrayList<>();
String name;
User(String name){
this.name=name;
if(this.name.equals("杨过")){
accounts.add(new Account("3217000010041315709",false));
accounts.add(new Account("3217000010041315715",false));
}
if(this.name.equals("郭靖")){
accounts.add(new Account("3217000010051320007",false));
}
if(this.name.equals("张无忌")){
accounts.add(new Account("3222081502001312389",false));
accounts.add(new Account("3222081502001312390",false));
accounts.add(new Account("3222081502001312399",false));
}
if(this.name.equals("韦小宝")){
accounts.add(new Account("3222081502051320785",false));
accounts.add(new Account("3222081502051320786",false));
}
if(this.name.equals("张三丰")){
accounts.add(new Account("3640000010045442002",true));
}
if(this.name.equals("令狐冲")){
accounts.add(new Account("3640000010045441009",true));
}
if(this.name.equals("乔峰")){
accounts.add(new Account("3630000010033431001",true));
}
if(this.name.equals("洪七公")){
accounts.add(new Account("3630000010033431008",true));
}
}
}
class Account{
meanless less=new meanless();
boolean kind;
String id;
ArrayList<Card> cards=new ArrayList<>();
double money;
Account(String id,boolean kind){
money=10000;
this.id=id;
this.kind=kind;
if(this.id.equals("3217000010041315709")){
cards.add(new Card("6217000010041315709"));
cards.add(new Card("6217000010041315715"));
}
if(this.id.equals("3217000010041315715")){
cards.add(new Card("6217000010041315718"));
}
if(this.id.equals("3217000010051320007")){
cards.add(new Card("6217000010051320007"));
}
if(this.id.equals("3222081502001312389")){
cards.add(new Card("6222081502001312389"));
}
if(this.id.equals("3222081502001312390")){
cards.add(new Card("6222081502001312390"));
}
if(this.id.equals("3222081502001312399")){
cards.add(new Card("6222081502001312399"));
cards.add(new Card("6222081502001312400"));
}
if(this.id.equals("3222081502051320785")){
cards.add(new Card("6222081502051320785"));
}
if(this.id.equals("3222081502051320786")){
cards.add(new Card("6222081502051320786"));
}
if(this.id.equals("3640000010045442002")){
cards.add(new Card("6640000010045442002"));
cards.add(new Card("6640000010045442003"));
}
if(this.id.equals("3640000010045441009")){
cards.add(new Card("6640000010045441009"));
}
if(this.id.equals("3630000010033431001")){
cards.add(new Card("6630000010033431001"));
}
if(this.id.equals("3630000010033431008")){
cards.add(new Card("6630000010033431008"));
}
}
void takemoney(double x){
if(x>this.money&&kind==false) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
if(x>this.money&&kind==true){
if(money>0){
if((less.returnme(x,(x-money)*0.05)-money)>50000) {
System.out.print("Sorry,your account balance is insufficient.");
System.exit(0);
}
x=less.returnme(x,-money);
this.money=0;
this.money-=x*1.05;
}
else {
if((less.returnme(x,x*0.05)-money)>50000) {
System.out.print("Sorry,your account balance is insufficient.");
System.exit(0);
}
this.money-=x*1.05;
}
}
else {
this.money -= x;
}
}
void takemoney(double x,double fee){
if(x*(1+fee)>this.money&&kind==false) {
System.out.print("Sorry,your account balance is insufficient.");
System.exit(0);
}
if(x>money&&kind==true){
if(money>0){
if((x+less.returnSum((x-money),0.05)+x*fee-money)>50000) {
System.out.print("Sorry,your account balance is insufficient.");
System.exit(0);
}
double z=money;
double y=less.returnSum(x,(1+fee))-money;
this.money=0;
this.money-=(less.returnme(y,less.returnSum(x-z,0.05)));
}
else {
if((x+x*0.05+x*fee-money)>50000) {
System.out.print("Sorry,your account balance is insufficient.");
System.exit(less.return0());
}
this.money-=(less.returnme(x*1.05,x*fee));
}
}
else {
this.money -= less.returnSum(x,(1+fee));
}
}
double getmoney(){
return money;
}
}
class Card{
String id;
Card(String id){
this.id=id;
}
}
class ATM{
String serialNumber;
ATM(String id){
this.serialNumber=id;
}
}
class meanless{
int less1=0;
public double returnme(double a,double b){
double key=6;
double c=a+b-5;
key=key+c-1;
return key;
}
public int return0(){
int a=7;
int c=6;
if(a-1==c){
return a*less1;
}
else
return less1;
}
public double returnSum(double a,double b){
double key=6;
double c=a*b-5;
key=key+c-1;
return key;
}
}
三、踩坑心得*
在题目集7(7-1)中,由于当时未发现Collection中的sort()方法,导致在对图形排序时,混合使用了简单的冒泡排序法和Comparable中的compare To()方法,使代码繁琐,在题目集7(7-2)中发现写好了Comparable中的compare To()方法后,可以直接用Collections对图形进行排序。
2.关于类的组合关系从小到大的查询
在题目集8的设计上,由于银联ChinaUnionPay中有多个银行Bank,银行Bank中有多个账户Account,多个用户User,多个ATM机ATM,用户User里面有多个账户Account,账户Account里面有多个卡号Card,各个类之间大都是一对多的组合关系,在ArrayList的使用下,从账户Account很容易找到各种卡号Card,那么如何根据卡号Card找到账号Account呢?在借鉴老师给的源码中发现了原来可以直接在Card类中定义一个Account account属性,然后在数据初始化卡号的时候,使用带Account的构造方法构造卡即可,利用getAccount()方法找到相应的账户。
四、改进建议
在这些题目集中,很多题目我都使用了简单而传统的for语句(int i = 0; i < xxx;i++),后面通过学习对比发现,这种最简单的for语句在遍历数据时耗时比较长,就目前我所学会的几种遍历方式中,增强for语句的耗时比较短,以后尽量使用增强for语句,同样,在不同的代码中也要改变相应的方法,在ArrayList中用for。
五、总结
从这三次题目集中学会了如何去设计一个类,先思考这个类的属性,作用等,再用封装,继承,多态技术去设计多个需要的类,在设计类之间的关系时,注意他们之间的关系(组合,依赖,关联等),也可以定义抽象类,利用抽象类中可能有抽象方法的特点,实现类型隐藏技术(因为继承的子类实现这个抽象方法时有很多种情况)。也可以利用接口实现多态性,提高程序的拓展性和可维护性。在设计代码的过程中,要学会运用面向对象的思想去设计一个程序,考虑"单一职责"原则、"开放封闭"原则、"Liskov替换原则"原则。