第三次博客作业
一、前言
第三次博客作业对7-9次的题集进行一次阶段性总结。
第7次题目集由于适逢劳动节,所以题量和难度上都有所降低。主要是对之前的类的继承、多态性使用方法以及接口的应用有一个复习巩固的作用。
第8次题集开始出现了新的题目类型,银行ATM的拟程序,这次作业更接近生活中的业务,所以难度上有所提升,题目分值比重变大,但题量所缩减
到一题。这次题集主目标是重点考核类的封装性及类间关系设计(关联、组合及依赖)。
第9次题目集在题目集8的基础上加入跨行业务,以及手续费和透支费用。其主要用到的知识还是题目集8的抽象类、继承与多态这些类间关系设计。
在难度上题目集8的一次进阶。题量上和题目集8一致。
二、设计与分析
①对于题目集7的7-1和7-2,是对图形对象做面积排序和对图形类型分组再排序。必须运用多态和继承。从题目7-1的类图:

来看,很显然圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid)都继承自Shape类,再运用多态进行数据引入。
由于老师给的源码中有数字标记,索性我在数据录入时运用这些数据。部分代码如下:
for(int i=0;i<List.size();i++) {
if(List.get(i).equals(1)) {
double radius =Main.input.nextDouble();
card = new Card(new Circle(radius));
cardList.add(card);
}
else if (List.get(i).equals(2)) {
double width = Main.input.nextDouble();
double length = Main.input.nextDouble();
card = new Card(new Rectangle(width,length));
cardList.add(card);
}
else if(List.get(i).equals(3)) {
double side1 = Main.input.nextDouble();
double side2 = Main.input.nextDouble();
double side3 = Main.input.nextDouble();
card = new Card(new Triangle(side1,side2,side3));
cardList.add(card);
}
else if(List.get(i).equals(4)){
double topside = Main.input.nextDouble();
double bottomside = Main.input.nextDouble();
double height = Main.input.nextDouble();
card = new Card(new Trapezoid(topside,bottomside,height));
cardList.add(card);
}
}
对于多态的运用如:
ArrayList<Card> cardList = new ArrayList<Card>();
card = new Card(new Trapezoid(topside,bottomside,height));
类图:

复杂图表:

对于7-2这道题加入了一个分组的功能,所以我的想法是将四种图形通过序号或标记分类,分别放入四个数组链表,部分代码如下:
ArrayList<Card> cardList1 = new ArrayList<Card>();
ArrayList<Card> cardList2 = new ArrayList<Card>();
ArrayList<Card> cardList3 = new ArrayList<Card>();
ArrayList<Card> cardList4 = new ArrayList<Card>();
先创建四个数组链表。在再创建图形是分别加入对应的数组链表如图:
类图以及复杂度图表如下:

可以看到,在复杂度上,7-2比7-1度高13.我估计是在7-1的基础上加入了四个数组链表的缘故。
②题目集8和题目集9
1.对于银行业务ATM虚拟程序的设计。我认为关系是:
一个银联下多个银行,每个银行下有多个ATM机和多个用户,每个用户下有多个账户,每个账户有多张卡。
所以我在初始化数据时创建了多个数组链表,对每一级进行储存。部分代码如下:

但是这样初始化数据的方法有一个极大地弊端,就是它的复杂度非常大,这是因为在初始化的过程中创建过多的数组链表。
图表和类图如下:

由于8-1中的代码初始化过程确实有欠缺,这在后期处理是用迭代器的方法几乎豪无作用,只能用一大堆for循环。后来老师给了处理的思路(
进行双向绑定)这样的处理对使用迭代器有了大大的便携性!这样的思路我便运用到了题目集9中:
初始化数据代码如下:
UnionPay unionPay = new UnionPay(0.05);
Bank ccb = new Bank("1001","中国建设银行",0.02);
Bank icbc = new Bank("1002","中国工商银行",0.03);
Bank abc = new Bank("1003","中国农业银行",0.04);
unionPay.addBank(ccb);
unionPay.addBank(icbc);
unionPay.addBank(abc);
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",abc);
ATM aTM8 = new ATM("08",abc);
ATM aTM9 = new ATM("09",abc);
ATM aTM10 = new ATM("10",abc);
ATM aTM11= new ATM("11",abc);
ccb.addATM(aTM1);
ccb.addATM(aTM2);
ccb.addATM(aTM3);
ccb.addATM(aTM4);
icbc.addATM(aTM5);
icbc.addATM(aTM6);
abc.addATM(aTM7);
abc.addATM(aTM8);
abc.addATM(aTM9);
abc.addATM(aTM10);
abc.addATM(aTM11);
User Yangguo = new User("360101200102122324","杨过","13856223254");
User Guojing = new User("360101200012302552","郭靖","13800021124");
User Zhangwuji = new User("360502199805163221","张无忌","13952110011");
User Weixiaobao = new User("360201200513243326","韦小宝","13025996587");
User Zhangsanfeng = new User ("360201200513243217","张三丰","13025990440");
User Linghuchong = new User ("360201200513243218","令狐冲","13025994134");
User Qiaofeng = new User ("360201200513243219","乔峰","13025990708");
User Hongqigong = new User ("360201200513243220","洪七公","13025999909");
Account ccbAcc1 = new Account("jj","3217000010041315709",10000.00,Yangguo,ccb);
Account ccbAcc2 = new Account("jj","3217000010041315715",10000.00,Yangguo,ccb);
Account ccbAcc3 = new Account("jj","3217000010051320007",10000.00,Guojing,ccb);
Account icbcAcc1 = new Account("jj","3222081502001312389",10000.00,Zhangwuji,icbc);
Account icbcAcc2 = new Account("jj","3222081502001312390",10000.00,Zhangwuji,icbc);
Account icbcAcc3 = new Account("jj","3222081502001312399",10000.00,Zhangwuji,icbc);
Account icbcAcc4 = new Account("jj","3222081502051320785",10000.00,Weixiaobao,icbc);
Account icbcAcc5 = new Account("jj","3222081502051320786",10000.00,Weixiaobao,icbc);
Account ccbAcc4 = new CreditAccount("jd","3640000010045442002",10000.00,Zhangsanfeng,ccb);
Account icbcAcc6 = new CreditAccount("jd","3640000010045441009",10000.00,Linghuchong,icbc);
Account abcAcc1 = new CreditAccount("jd","3630000010033431001",10000.00,Qiaofeng,abc);
Account abcAcc2 = new CreditAccount("jd","3630000010033431008",10000.00,Hongqigong,abc);
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);
icbc.addAccount(icbcAcc6);
abc.addAccount(abcAcc1);
abc.addAccount(abcAcc2);
Yangguo.addAccount(ccbAcc1);
Yangguo.addAccount(ccbAcc2);
Guojing.addAccount(ccbAcc3);
Zhangwuji.addAccount(icbcAcc1);
Zhangwuji.addAccount(icbcAcc2);
Zhangwuji.addAccount(icbcAcc3);
Weixiaobao.addAccount(icbcAcc4);
Weixiaobao.addAccount(icbcAcc5);
Zhangsanfeng.addAccount(ccbAcc4);
Linghuchong.addAccount(icbcAcc6);
Qiaofeng.addAccount(abcAcc1);
Hongqigong.addAccount(abcAcc2);
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",icbcAcc5);
Card ccbCard11 = new CreditCard("6640000010045442002","88888888",ccbAcc4);
Card ccbCard12 = new CreditCard("6640000010045442003","88888888",ccbAcc4);
Card icbcCard13 = new CreditCard("6640000010045441009","88888888",icbcAcc6);
Card abcCard14 = new CreditCard("6630000010033431001","88888888",abcAcc1);
Card abcCard15 = new CreditCard("6630000010033431008","88888888",abcAcc2);
ccbAcc1.addCard(ccbCard1);
ccbAcc1.addCard(ccbCard2);
ccbAcc2.addCard(ccbCard3);
ccbAcc3.addCard(ccbCard4);
ccbAcc4.addCard(ccbCard11);
ccbAcc4.addCard(ccbCard12);
icbcAcc1.addCard(icbcCard5);
icbcAcc2.addCard(icbcCard6);
icbcAcc3.addCard(icbcCard7);
icbcAcc3.addCard(icbcCard8);
icbcAcc4.addCard(icbcCard9);
icbcAcc5.addCard(icbcCard10);
icbcAcc6.addCard(icbcCard13);
abcAcc1.addCard(abcCard14);
abcAcc2.addCard(abcCard15);
这样一来,用户便和银行没有关系,而是通过绑定账户来间接绑定银行。
其类图和复杂如下:


可以看到在复杂度上有了大大的降低!
三、采坑心得
1、对于题目集7的7-1,有一句提示:
/在Main类中定义一个静态Scanner对象,这样在其它类中如果想要使用该对象进行输入,则直接
//使用Main.input.next…即可(避免采坑)
在这之前我在每个需要输入数据的方法中读写一句:
Scanner input = new Scanner(System.in);
这样的一句提示,对我以后写代码提供了方便,也是代码在封装性上更好。
另外在指导书中写到:本程序仅用于为学生所玩的游戏提供正确答案的功能,即根据学生得到的卡片种类与数量,给出 排序前和排序后的卡片顺序,同时给出所有卡片的面积之和。
这显然是提示我们使用数组的方法进行储存,但为了更好的体现多态的运用,我用了ArraryList的方法。
提示里面提到比较大小的方法Comparable 接口中的 CompareTo(),在此之前,我肯是用冒泡排序的方法。通过查阅资料,我发现Comparable 接口在Java中的库里自带!
所以我直接将Card介入接口Comparable:
class Card implements Comparable<Card>
并在CompareTo()方法中传入Card类型如:
public int compareTo(Card card) {
if(this.getShape().getArea()>card.getShape().getArea()) {
return -1;
}
return 1;
}
再加入一句Collections.sort(cardList);来对卡片按面积排序;
(2)、在7-2中,只是加入分组的方法,另创建了四个数组链表。其大致的处理代码和7-1一致。所以这里对7-2不作分析。
(3)、题目集8中,由于我是创建多个数组链表来初始化,所以迭代器基本上对我的算法无效。(前面提到)。所以我用了大量的for循环:
public boolean cheakatm() {
for (int s = 0; s < m.bankList.size(); s++) {
for (int i = 0; i < m.bankList.get(s).getUserList().size(); i++) {
for (int j = 0; j < m.bankList.get(s).getUserList().get(i).accountList.size(); j++) {
for (int n = 0; n < m.bankList.get(s).getUserList().get(i).accountList.get(j).cardtList.size(); n++) {
if (a[0].equals(m.bankList.get(s).getUserList().get(i).accountList.get(j).cardtList.get(n)
.getCard_number())) {
for(int q=0;q<m.bankList.get(s).getAtmList().size();q++) {
if(a[2].equals(m.bankList.get(s).getAtmList().get(q).getNumber()))
return true;
}
}
}
}
}
}
return false;
}
public boolean cheakmoney() {
double d=Double.parseDouble(a[3]);
for(int i=0;i<m.List.size();i++) {
for(int j = 0;j<m.List.get(i).cardtList.size();j++) {
if(a[0].equals(m.List.get(i).getCardtList().get(j).getCard_number())) {
if(m.List.get(i).getBalance()-d<0)
return false;
}
}
}
return true;
}
public void money() {
double d1 = Double.parseDouble(a[3]);
for (int s = 0; s < m.bankList.size(); s++) {
for (int i = 0; i < m.bankList.get(s).getUserList().size(); i++) {
for (int j = 0; j < m.bankList.get(s).getUserList().get(i).accountList.size(); j++) {
for (int n = 0; n < m.bankList.get(s).getUserList().get(i).accountList.get(j).cardtList.size(); n++) {
if (a[0].equals(m.bankList.get(s).getUserList().get(i).accountList.get(j).cardtList.get(n)
.getCard_number())) {
m.bankList.get(s).getUserList().get(i).accountList.get(j).reduce_balance(d1);
if (d1 < 0)
System.out.println(m.bankList.get(s).getUserList().get(i).getName() + "在" + m.bankList.get(s).getName()+ "的" + a[2] + "号ATM机上存款¥" + String.format("%.2f", -d1));
else
System.out.println(m.bankList.get(s).getUserList().get(i).getName() + "在" + m.bankList.get(s).getName()
+ "的" + a[2] + "号ATM机上取款¥" + String.format("%.2f", d1));
System.out.println("当前余额为¥" + String.format("%.2f",
m.bankList.get(s).getUserList().get(i).accountList.get(j).getBalance()));
}
}
}
}
}
}
public void cheackbalance() {
for (int s = 0; s < m.bankList.size(); s++) {
for (int i = 0; i < m.bankList.get(s).getUserList().size(); i++) {
for (int j = 0; j < m.bankList.get(s).getUserList().get(i).accountList.size(); j++) {
for (int n = 0; n < m.bankList.get(s).getUserList().get(i).accountList.get(j).cardtList.size(); n++) {
if (a[0].equals(m.bankList.get(s).getUserList().get(i).accountList.get(j).cardtList.get(n)
.getCard_number())) {
System.out.println( "¥"+String.format("%.2f",
m.bankList.get(s).getUserList().get(i).accountList.get(j).getBalance()));
}
}
}
}
}
}
}
这样大大减低了处理数据的效率!
在题目集9中,通过双向绑定,使用迭代器的方法直接找到我要处理的对象,大大提高了效率,代码示例如下:

四、改进建议
(1)由于为了能够更好的体现开闭原则,在题目集9中,我在处理各种手续问题时,通过税率绑定的方法我将每个银行对应的税率与对应银行绑定,如:
Bank ccb = new Bank("1001","中国建设银行",0.02);
Bank icbc = new Bank("1002","中国工商银行",0.03);
Bank abc = new Bank("1003","中国农业银行",0.04);
在计算时就不必通过银行来处理,大大提高效率!代码如下:
if (!account.getBank().getBankNO().equals(aTM.getBank().getBankNO())) {
if (account.getType().equals("jd")&& amount > balance&&balance>=0) {//借贷卡即跨行又透支且余额为正
s= amount*aTM.getBank().getShuilu()+amount+(amount-balance)*unionPay.getShuilu();
}
else if (account.getType().equals("jd")&& amount > balance&&balance<0) {//借贷卡即跨行又透支且余额为非正
s= amount*aTM.getBank().getShuilu()+amount+(amount)*unionPay.getShuilu();
}
else if ((account.getType().equals("jd")&& amount <=balance&&balance>=0)||account.getType().equals("jj")) {//借贷卡或借记卡跨行不透支
s= amount*aTM.getBank().getShuilu()+amount;
}
}
/**
* 不跨行取款操作
*/
else{
if(account.getType().equals("jd")&&account.getBalance()<s&&account.getBalance()>0) {
s= amount+(amount-balance)*unionPay.getShuilu();
}
if(account.getType().equals("jd")&&account.getBalance()<s&&account.getBalance()<0) {
s= amount+(amount)*unionPay.getShuilu();
}
}
return s;
}
五、总结
(1)随着学习的深入,每次的题目集在难度上有了提高,这次的三次题目集又增加了类的继承,聚合,多态以及接口引用 。这三次题目集中,更具综合性更有难度的其实是题目集9。这里我谈谈我对聚合和多态的理解:如果类B聚合于类A,那其实是是将B作为类A中的一个属性。
所谓的“多态”,简单的理解就是对象在不同情况下的不同表现,具体体现在定义和功能两个方 面,简单的总结一下,多态可以用“三个定义和两个方法”来总结。三个定义分别是父类定义子类构 建、接口定义实现类构建和抽象类定义实体类构建,而两个方法分别是方法重载和方法重写。
通过本次题目集的学习,我还了解到了接口,前面也提到过,接口相当于一个完全抽象的抽象类,其中有抽象方法,而接口和抽象类一个重要的区别就是接口中只有抽象方法和常量,但接口可以进行多继承,这是两者的区别,使用接口可以提高代码的可维护性和扩展性,且接口可以减少代码的书写,学会使用接口对我们专业的学习非常有帮助。我现在还只了解接口的大概,还需要进一步地去学习接口。
(2)另外,对这个学期的学习做一些个人总结以及对课程学习提一些相关的意见
①由于该课程是线上线下混合式的教学,这对我们的自学能力有了一些要求。但实际上,我所面对的问题是,在查找资料时往往无从查起,这使得我认为我的学习
效率太低,在一定吃程度上打击了我的信心。
②对课程的建议时,希望老师在每次讲完课后,对下一节课学习任务有一个预告,最好是说相关知识在课本多少多少页,对于听网课,我们可能更倾向于看得见摸得着的解读内容,这样不仅在看的过程中不只是看,还能敲一敲。
总之,这三次的题目集让我对前面学到的知识有了更深入的理解和巩固!

浙公网安备 33010602011771号