Blog作业三

前言:

1.总的来说,题目七到题目九题目量相对减少,但是题目的难度确实大大的增加,一共有四道题目,但是四道题目都是逐一不断演化而成的。

2.题目集七有两道题都是关于卡牌类游戏的问题,第二题是由第一题演化的来。题目集八就是设计一个简单的ATM机的模型里面并没有设计到很多其他的内容。题目集九就是从题目集八演化得来的,里面添加了很多其他的类和不同的元素,以提高题目的难度,使代码的长度有了大大的增加。

3.知识点:(一)题目集七的两道题要求了对继承和多态的理解,并且对方法的设置和调用,以及属性私有化的考察。(二)ATM机考察了全部Java课程所学的知识点除了javafx,题目综合性非常的强。

先来分析一下第七次作业的两道题:

首先看题目7-1:这道题是图形卡片排序游戏他的类图为下

 

 7-1的作业:考虑一款适合于小学生的卡片(Card)排序游戏,其规则为随机发放一些卡片给学生,卡片分为 四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid),并给出各种 卡片的相应参数,要求学生能够迅速求出各卡片的面积大小然后将卡片按照其面积值从大到小进行排 序,同时求出所有卡片的面积之和。

分析:

此题目考查的知识点有接口的定义,接口的使用,主要是对Comparable接口的定义和使用,Comparable接口主要的作用是对两个类进行比较,是某个类的两个实例对象之间进行比较的手段,比如现在有有两个类,是某同一个类new出来的对象,如果要对这两个类里面的某一个属性进行比较可以是由Comparable接口,具体做法就是让该类继承Comparable接口,然后重写Comparable接口,

 

很明显需要用到继承的方法,所以要建立一个父类:
abstract class Shape {
private String shapeName;

public String getShapeName() {
return shapeName;}

public void setShapeName(String shapeName) {
this.shapeName = shapeName;
}

public Shape() {
super();
}

public Shape(String shapeName) {
super();
this.shapeName = shapeName;
}

public double getArea() {
return 0.0;
}

public boolean validate() {
return true;
}
}然后题目中其他的什么矩形类啊,圆形类,还有其他形状的类都可以继承这个父类来实现其独自的方法功能。.我们大致确定类有哪些后,就可以对每一个类的属性和方法进行分析,首先我们从圆形开始分析,圆形属性肯定的有半径这一属性,再此题中除此之外没有其他属性,接着我们考虑类的方法,圆的话肯定的有计算圆的面积的方法,以及校验对圆半径数据设置的合法性的方法,接着我们考虑圆的半径的初始化应该怎么做,初始化的手段有通过构造放法,通过set get设置。

class DealCardList{
ArrayList<Card> cardList=new ArrayList<>();

public DealCardList() {
}

public DealCardList(ArrayList<Integer> card) {
for (Integer integer : card) {
if (integer==0)break;
switch (integer){
case 1:
Card card1=new Card(new Circle(Main.input.nextDouble()));
card1.getShape().setShapeName("Circle");
cardList.add(card1);
break;
case 2:
Card card2=new Card(new Rectangle(Main.input.nextDouble(),Main.input.nextDouble()));
card2.getShape().setShapeName("Rectangle");
cardList.add(card2);
break;
case 3:
Card card3=new Card(new Triangle(Main.input.nextDouble(),Main.input.nextDouble(),Main.input.nextDouble()));
card3.getShape().setShapeName("Triangle");
cardList.add(card3);
break;
case 4:
Card card4=new Card(new Trapezoid(Main.input.nextDouble(),Main.input.nextDouble(),Main.input.nextDouble()));
card4.getShape().setShapeName("Trapezoid");
cardList.add(card4);
break;
}

}
}然后再通过设置选项诱导操作者进行选择对应的图形,再在选择的时候加入对应的方法。

题目7-2:

沿袭作业 7-1,本次作业主要对卡片(Card)进行分组游戏,其规则为随机发放一些卡片给学生, 卡片仍然分为四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid), 并给出各种卡片的相应参数,要求学生首先根据卡片类型将所有卡片进行分组(一个类型分为一组, 所以最多四组),然后能够对每组内的卡片根据面积值从大到小进行排序,同时求出该组内所有卡片 的面积之和,最后求出每组卡片面积之和中的最大值。

 其对应的类图其实和题目7-1差不多,但还是有些许的改动

 

重点是Comparable 接口的应用:
interface Compare {
public int compareTo(Card card);
}

class Card implements Compare {
Shape shape;

public Shape getShape() {
return shape;
}

public void setShape(Shape shape) {
this.shape = shape;
}

public Card(Shape shape) {
super();
this.shape = shape;
}

public Card() {
super();
}

@Override
public int compareTo(Card card) {
return 0;
}
}

在完成本题的时候我犯了一个错误就是没有看清楚题目排序前的各图形类型及面积,格式为[图形名称1:面积值1图形名称2:面积值2 …图形名称n:面积值n ],注意,各图形输出之间用空格分开,且输出最后存在一个用于分隔的空格,在结束符“]”之前;导致输出的和之前的题目比较像,又使我重新去看代码去进行繁琐的改查。

现在来看看题目集八,也就是综合练习的一次作业,这次的作业是要求设计一个ATM仿真机,但是不是完全设计出来的可以使用的完全体,只是普通的雏形。

 

以上是本题的类图,是一个非常复杂的图,这图里面有很多类很多关系,类里面也包含了很多不同的对象。

 

这个是他简单的需要设计的东西。所以对于每一个我都设计了一个独特的方法来进行。最后通过一个control的方法使这个程序能够正常的运行。

 

 

 

 通过所需要的几个类:银行(Bank),银行用户(Person),银行账户(Account),银行卡(Card)完成功能取款和查询。
其中特别需要注意的是List<String> list=new ArrayList<String>()
接口,可以将对象的使用标准化,即面向接口编程。父类为接口,规定使用的方法;子类为各种不同的具体实现,根据实际需求选用不同的实现。

public class User {
private String name;
public User(String name) {
// TODO 自动生成的构造函数存根
this.name=name;
}
public String getName() {
return name;
}

}

本道题需要使用到多次多态的使用和方法的调用,从银联类开始,银联类比较简单,我们咋思考类到底有哪些属性时,很简单,联想一下生活即可,想一下在生活中该类到底是怎样的,银联就是对银行的汇总,他是对银行的管理,所以银联类属性就是存储银行类的一个列表,接下来,我们来想一下该链表和银联类的关系,银行并不是银联所独有的,外部数据可以共享到银联里的数据,比如用户跨行取款就要使用到银联里的数据,而且同时银联里面有银行这一属性,但是银联里面可以暂时没有银行,即没有银行加入银联,综上分析后,银联和银行的关系时关联关系,关系已明确,我们就可以设计该属性的初始化数据的方法了,既然是关联关系,我们就可以通过set get方式进行初始化。也可以使用带参数的构造方法,但是使用带参数的构造方法后,就必需加上我参数的构造方法,因为是关联关系,如果只有带参数的构造方法,那么就变成了聚合关系,银联类就是这样。接下来,我们看一下银行类,首先属性里面肯定必须要有银行的号,银行名字,银行里面存的用户信息,所以还需要一个用户列表属性,同时还需要ATM机列表属性,同时不同的银行有不同的取款收费率,所以还学要有一个取款收费率的属性,接下来我们一个一个看他们这些属性和银行是什么关系,首先是银行号和银行的名字,所有的银行都有一个银行号和相应的名字,不管什么情况这都是必须的。

题目集9就是在题目集的八上扩展了对应的程序,列如借贷系统,和税率的系统,以及多加了一个银行凑够之前的两个银行变成了三个银行之间的转换。

 

 以上为题目九的类图,(1)务必注意本题目中的各实体类之间的关系,尤其是一对多的组合关系。 (2)对实体类的设计要做到单一职责原则,且不能缺少规定的实体类。 (3)在“合成复用原则”及“单一职责原则”基础上,尽量对上次作业的程 序进行重构,使之符合 “开-闭”原则。

加了一个借贷卡的使用,同时加了借贷账户和借记账户的区别使用,这就运用到了多态的使用,而且从上一次的作业的教训来看,这次的代码虽然老师给出了部分代码,但一些核心代码还是需要自己来完成的,这次的问题主要是解决两种卡的区别,如何将两种卡分辨出来,或者如何让两张卡进行不同的取钱程序,而且这次代码需要增加跨行取款的内容,这也是需要考虑到的一方面,但是有些代码,例如如何从卡号知道所属银行,知晓账户,这些老师已经给出的代码,无疑让代码的难度降低了一点。从类图也可以看出来,除了两个账户的多态,其他的类图就比较简单,而且这个代码的圈复杂度也不是很高,可能有一部分是老师的代码原因。

 

package ATM机;

public class Contraler {
private ChinaUnionPay union;
public Contraler(ChinaUnionPay union) {
// TODO 自动生成的构造函数存根
this.union=union;
}
public void deal(String cardNum,String keyNum,String atmNum,double money) {
Bank bank=null;
Account account=null;
if(!checkcardNum(cardNum)){
System.out.println("Sorry,this card does not exist.");
System.exit(0);
}
if(!checkAtmNum(atmNum)) {
System.out.println("Sorry,the ATM's id is wrong.");
System.exit(0);
}
if(!checkKey(keyNum)) {
System.out.println("Sorry,your password is wrong.");
System.exit(0);
}
if(!checkMoney(cardNum, money)) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
if(!checkCrossBank(cardNum, atmNum)) {
System.out.println("Sorry,cross-bank withdrawal is not supported.");
System.exit(0);
}
for(int i=0;i<union.getBankGroup().size();i++) {
for(int j=0;j<union.getBankGroup().get(i).getAccounts().size();j++) {
for(int k=0;k<union.getBankGroup().get(i).getAccounts().get(j).getCardGroup().size();k++) {
if(union.getBankGroup().get(i).getAccounts().get(j).getCardGroup().get(k).getCardNum().equals(cardNum)) {
bank=union.getBankGroup().get(i);
account=union.getBankGroup().get(i).getAccounts().get(j);
}
}
}

}
if(money<0) {
deposit(account, money);
System.out.println(account.getUser().getName()+"在"+bank.getBankName()+"的"+atmNum+"上存款¥"+String.format("%.2f", (-money)));
System.out.println("当前余额为¥"+String.format("%.2f",account.getMoney()));
}
else {
withDraw(account, money);
System.out.println(account.getUser().getName()+"在"+bank.getBankName()+"的"+atmNum+"上取款¥"+String.format("%.2f", (money)));
System.out.println("当前余额为¥"+String.format("%.2f",account.getMoney()));
}
}
public void deal(String cardNum) {
if(!checkcardNum(cardNum)){
System.out.println("Sorry,this card does not exist.");
System.exit(0);
}
Account account=null;
for(int i=0;i<union.getBankGroup().size();i++) {
for(int j=0;j<union.getBankGroup().get(i).getAccounts().size();j++) {
for(int k=0;k<union.getBankGroup().get(i).getAccounts().get(j).getCardGroup().size();k++) {
if(union.getBankGroup().get(i).getAccounts().get(j).getCardGroup().get(k).getCardNum().equals(cardNum))
account=union.getBankGroup().get(i).getAccounts().get(j);
}
}

}
System.out.println("¥"+String.format("%.2f",account.getMoney()));
}
public boolean checkCrossBank(String cardNum,String atmNum) {
Bank bank=null;
for(int i=0;i<union.getBankGroup().size();i++) {
for(int j=0;j<union.getBankGroup().get(i).getAtms().size();j++) {
if(union.getBankGroup().get(i).getAtms().get(j).getAtmNum().equals(atmNum)) {
bank=union.getBankGroup().get(i);
}
}
}
for(int i=0;i<bank.getAccounts().size();i++) {
for(int j=0;j<bank.getAccounts().get(i).getCardGroup().size();j++) {
if(bank.getAccounts().get(i).getCardGroup().get(j).getCardNum().equals(cardNum)) {
return true;
}
}
}
return false;
}
public boolean checkAtmNum(String atmNum) {
for(int i=0;i<union.getBankGroup().size();i++) {
for(int j=0;j<union.getBankGroup().get(i).getAtms().size();j++) {
if(union.getBankGroup().get(i).getAtms().get(j).getAtmNum().equals(atmNum)) {
return true;
}
}
}
return false;
}
public boolean checkKey(String key){
return key.equals("88888888");
}
public boolean checkcardNum(String cardNum) {
for(int i=0;i<union.getBankGroup().size();i++) {
for(int j=0;j<union.getBankGroup().get(i).getAccounts().size();j++) {
for(int k=0;k<union.getBankGroup().get(i).getAccounts().get(j).getCardGroup().size();k++) {
if(union.getBankGroup().get(i).getAccounts().get(j).getCardGroup().get(k).getCardNum().equals(cardNum))
return true;
}
}

}
return false;
}
public boolean checkMoney(String cardNum,double money) {
Account account=null;
for(int i=0;i<union.getBankGroup().size();i++) {
for(int j=0;j<union.getBankGroup().get(i).getAccounts().size();j++) {
for(int k=0;k<union.getBankGroup().get(i).getAccounts().get(j).getCardGroup().size();k++) {
if(union.getBankGroup().get(i).getAccounts().get(j).getCardGroup().get(k).getCardNum().equals(cardNum))
account=union.getBankGroup().get(i).getAccounts().get(j);
}
}

}
return account.getMoney()>money;
}
public void deposit(Account account,double money) {
account.takeMoney(money);
}
public void withDraw(Account account,double money) {
account.takeMoney(money);
}
}这个就是控制所有输出输入的控制器。

总结:

这三次的作业相对于之前的所有作业都是很难的存在,他们的综合性考察非常的强,需要有很强的Java素养才能轻松做出这些题,但是我在做这些题的时候都是非常的费力的,并且在一写点上面花费了大量的时间和实践去做,并且做错直接不能及时的改正。通过本次题目集的学习,我还了解到了接口,前面也提到过,接口相当于一个完全抽象的抽象类,其中有抽象方法,而接口和抽象类一个重要的区别就是接口中只有抽象方法和常量,但接口可以进行多继承,这是两者的区别,使用接口可以提高代码的可维护性和扩展性,且接口可以减少代码的书写,学会使用接口对我们专业的学习非常有帮助。我现在还只了解接口的大概,还需要进一步地去学习接口。

踩坑:

ATM机问题遇到的问题就比较多了,而且第一次的代码老师也没有给出一些源码之类的,所以全部代码都自己完成,根据老师之前的例子,一直使用迭代器,每一个都需要从头找到尾,简直了,如图,还有每个类之间的联系和绑定,我也是在老师把他代码给出来的时候知道两者可以双向绑定,而自己的代码就是一个个绑定,光是最开始的初始化,就把人累的不轻,我又是一个银行一个银行开始的,最后每个卡绑定完后我都觉得可能绑错了,还检查了好久,生怕因为初始化没有完成,最后导致最后结果错误,那直接泡汤,而且检查起来也会很麻烦,而且最开始的输入字符串处理就遇到了问题,这个字符串该从那些地方对它进行分割,该怎么样分割,这个问题也困扰了我很久,最后把他们放在不同的组里面才完成这个代码,而且输出方面,每次需要对输入的东西进行检测。

 

posted @ 2021-06-20 20:48  浮云2  阅读(38)  评论(0)    收藏  举报