OO第七-第九次作业总结
OO第七-第九次作业总结
1、前言(对三次作业的总结)
这三次分别考查了:1.掌握类的继承、多态性使用方法以及接口的应用。2.3.面向对象思维的考查。
题量:三次的题量相差无几。
难度:第七次是第一次接触到大量接口的使用,我认为是最难的。第八第九次虽然代码量与思维更加严密,但是难度适中。
2、设计与分析
1.nchu-software-oop-7
先上老师要求的UML类图:

其中Card类需要继承comparable接口,shape为所有图形的父类。用代码实现后的类图如下:


基本完成老师所需要求。这道题的关键在与对输入的正则表达式分割以及分割之后的排序的实现过程,其次便是对UML图中类与方法等面向对象部分的解读与实现。

而第二题增加了多个同种卡片的排序以及计算过程,增加了所需要的计算量,同时10kb的代码长度限制也要求我们拥有更加简洁,更加具有复用性的代码,而这也就是面向对象编程所要求的。
我增加了若干个方法来简化主函数中的分割以及判定过程,并且优化了大量无用的代码:

从如图的大量的for循环在main方法中进行判定然后再传到类中的相应方法中进行处理的极其面向过程的思维转化为了

这样的全部由类中的方法进行一切判定以及分割工作的main方法,实现了从面向过程向面向对象的转换。
2.nchu-software-oop-8
这道题如果使用面向过程的方法进行编程的话会使得我们的主方法的内容极大的延长。因此我们需要好好理清多个类之间的关系。
一个用户可以在多个银行有多个银行账户;一个银行可以有多个用户的多个银行账户;一个账户只能有一个所属的银行以及一个对应的用户。
由此可见:用户与银行是多对多的关系;银行与账户是一对多的关系;用户与账户是一对一的关系;
银行与账户的关系为依赖;
用户与账户的关系为依赖;
账户与用户和银行的关系均为依赖;
知道了三者之间的关系之后,我们便可以明显的看出账户时我们编码时的中心,用于关联三者。
于是便可产生如下类图:

| Main | BankUnion | BankNum | User | ATM | Bank | CardNum |
| 主类 | 银联类 | 银行账户类 | 用户类 | ATM机类 | 银行类 | 卡号类 |
至此类之间的关系已经完全明了,我们现在需要做的是如何进行接下来的进行方法的调用。
属性的初始化就不赘述了,我们需要考虑的是取款与存款中的情况。(这部分因为与作业九相近,将在作业九中细说)
最后附上全部代码:
nchu-software-oop-8代码
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
ArrayList<BankNum> bankNumS = new ArrayList<>();
//初始化银行
Bank CCB = new Bank("中国建设银行");//建行
Bank ICBC = new Bank("中国工商银行");//工商
BankUnion bankUnion = new BankUnion();
bankUnion.getBanks().add(CCB);
bankUnion.getBanks().add(ICBC);
//初始化ATM
for (int i = 1 ;i <= 4 ;i++)
CCB.getATM().add(new ATM("0"+i));
for (int i = 5 ;i <= 6 ;i++)
ICBC.getATM().add(new ATM("0"+i));
//初始化用户
User YangGuo = new User("杨过");
User GuoJing = new User("郭靖");
User ZhangWuJi = new User("张无忌");
User WeiXiaoBao = new User("韦小宝");
//初始化银行账号
BankNum bankNum1=new BankNum("3217000010041315709");
BankNum bankNum2=new BankNum("3217000010041315715");
BankNum bankNum3=new BankNum("3217000010051320007");
BankNum bankNum4=new BankNum("3222081502001312389");
BankNum bankNum5=new BankNum("3222081502001312390");
BankNum bankNum6=new BankNum("3222081502001312399");
BankNum bankNum7=new BankNum("3222081502051320785");
BankNum bankNum8=new BankNum("3222081502051320786");
//加入链表
bankNumS.add(bankNum1);
bankNumS.add(bankNum2);
bankNumS.add(bankNum3);
bankNumS.add(bankNum4);
bankNumS.add(bankNum5);
bankNumS.add(bankNum6);
bankNumS.add(bankNum7);
bankNumS.add(bankNum8);
//初始化银行以及用户卡号
CCB.getBankNumS().add(bankNum1);bankNum1.setBank(CCB);
YangGuo.getBankNumS().add(bankNum1);bankNum1.setUser(YangGuo);
bankNum1.getCardNumS().add(new CardNum("6217000010041315709"));
bankNum1.getCardNumS().add(new CardNum("6217000010041315715"));
CCB.getBankNumS().add(bankNum2);bankNum2.setBank(CCB);
YangGuo.getBankNumS().add(bankNum2);bankNum2.setUser(YangGuo);
bankNum2.getCardNumS().add(new CardNum("6217000010041315718"));
CCB.getBankNumS().add(bankNum3);bankNum3.setBank(CCB);
GuoJing.getBankNumS().add(bankNum3);bankNum3.setUser(GuoJing);
bankNum3.getCardNumS().add(new CardNum("6217000010051320007"));
ICBC.getBankNumS().add(bankNum4);bankNum4.setBank(ICBC);
ZhangWuJi.getBankNumS().add(bankNum4);bankNum4.setUser(ZhangWuJi);
bankNum4.getCardNumS().add(new CardNum("6222081502001312389"));
ICBC.getBankNumS().add(bankNum5);bankNum5.setBank(ICBC);
ZhangWuJi.getBankNumS().add(bankNum5);bankNum5.setUser(ZhangWuJi);
bankNum5.getCardNumS().add(new CardNum("6222081502001312390"));
ICBC.getBankNumS().add(bankNum6);bankNum6.setBank(ICBC);
ZhangWuJi.getBankNumS().add(bankNum6);bankNum6.setUser(ZhangWuJi);
bankNum6.getCardNumS().add(new CardNum("6222081502001312399"));
bankNum6.getCardNumS().add(new CardNum("6222081502001312400"));
ICBC.getBankNumS().add(bankNum7);bankNum7.setBank(ICBC);
WeiXiaoBao.getBankNumS().add(bankNum7);bankNum7.setUser(WeiXiaoBao);
bankNum7.getCardNumS().add(new CardNum("6222081502051320785"));
ICBC.getBankNumS().add(bankNum8);bankNum8.setBank(ICBC);
WeiXiaoBao.getBankNumS().add(bankNum8);bankNum8.setUser(WeiXiaoBao);
bankNum8.getCardNumS().add(new CardNum("6222081502051320786"));
//主要工程
Scanner input = new Scanner(System.in);
String s = input.nextLine();
String []project;
BankNum bankNum;
while (!s.equals("#"))
{
String name,Bank,ATM = null;
Double money = 0.0;
bankNum = null;
String regex = "\\s+";
s = s.replaceAll(regex, " ");
project = s.split(" ");
if (project.length != 1)
{
for (BankNum num : bankNumS) {
for (int j = 0; j < num.getCardNumS().size(); j++) {
if (project[0].equals(num.getCardNumS().get(j).getNum())) {
bankNum = num;
break;
}
}
if (bankNum != null)
break;
}
if (bankNum == null)
{
System.out.println("Sorry,this card does not exist.");
return;
}
else
{
name = bankNum.user.getName();
Bank = bankNum.bank.getName();
if (!project[1].equals("88888888"))
{
System.out.println("Sorry,your password is wrong.");
return;
}
else
{
for (int i = 0; i < bankNum.getBank().getATM().size(); i++)
{
if (bankNum.getBank().getATM().get(i).getNum().equals(project[2]))
{
ATM = project[2];
break;
}
}
if (ATM != null)
{
if (Double.parseDouble(project[3]) >= 0)
{
money = bankNum.getMoney() - Double.parseDouble(project[3]);
if (money < 0) {
System.out.println("Sorry,your account balance is insufficient.");
return;
}
bankNum.setMoney(bankNum.getMoney() - Double.parseDouble(project[3]));
System.out.println(name+"在"+Bank+"的"+ATM+"号ATM机上取款¥"+project[3]);
System.out.printf("当前余额为¥%.2f\n",money);
}
if (Double.parseDouble(project[3]) < 0)
{
money = bankNum.getMoney() - Double.parseDouble(project[3]);
regex = "-";
project[3] = project[3].replaceAll(regex,"");
bankNum.setMoney(bankNum.getMoney() + Double.parseDouble(project[3]));
System.out.println(name+"在"+Bank+"的"+ATM+"号ATM机上存款¥"+project[3]);
System.out.printf("当前余额为¥%.2f\n",money);
}
}
else
{
String error = null;
for (int i = 0; i < bankUnion.getBanks().size() && error == null; i++)
{
for (int j = 0; j < bankUnion.getBanks().get(i).getATM().size() ; j++)
{
if (bankUnion.getBanks().get(i).getATM().get(j).getNum().equals(project[2]))
{
error = project[2];
break;
}
}
}
if (error == null)
System.out.println("Sorry,the ATM's id is wrong.");
else
System.out.println("Sorry,cross-bank withdrawal is not supported.");
return;
}
}
}
}
else
{
for (BankNum num : bankNumS) {
for (int j = 0; j < num.getCardNumS().size(); j++) {
if (project[0].equals(num.getCardNumS().get(j).getNum())) {
bankNum = num;
break;
}
}
if (bankNum != null)
break;
}
if (bankNum == null)
{
System.out.println("Sorry,this card does not exist.");
return;
}
else
{
System.out.printf("¥%.2f\n",bankNum.getMoney());
}
}
s = input.nextLine();
}
}
}
class BankUnion{
ArrayList<Bank>banks = new ArrayList<>();
public void addBanks(Bank bank){
getBanks().add(bank);
}
public ArrayList<Bank> getBanks() {
return banks;
}
public void setBanks(ArrayList<Bank> banks) {
this.banks = banks;
}
}
class BankNum{
ArrayList<CardNum> cardNumS = new ArrayList<>();
Bank bank = new Bank();
User user = new User();
private String BankNum;
private Double money = 10000.00;
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Bank getBank() {
return bank;
}
public void setBank(Bank bank) {
this.bank = bank;
}
public BankNum() {
}
public BankNum(String bankNum) {
BankNum = bankNum;
}
public ArrayList<CardNum> getCardNumS() {
return cardNumS;
}
public void setCardNumS(ArrayList<CardNum> cardNumS) {
this.cardNumS = cardNumS;
}
public String getBankNum() {
return BankNum;
}
public void setBankNum(String bankNum) {
BankNum = bankNum;
}
}
class Bank{
ArrayList<BankNum> bankNumS = new ArrayList<>();
private String name;
ArrayList<ATM> ATM = new ArrayList<>();
public Bank() {
}
public Bank(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<ATM> getATM() {
return ATM;
}
public void setATM(ArrayList<ATM> ATM) {
this.ATM = ATM;
}
public void addATM(ATM atm)
{
getATM().add(atm);
}
public ArrayList<BankNum> getBankNumS() {
return bankNumS;
}
public void setBankNumS(ArrayList<BankNum> bankNumS) {
this.bankNumS = bankNumS;
}
}
class User{
ArrayList<BankNum> bankNumS = new ArrayList<>();
private String name;
public ArrayList<BankNum> getBankNumS() {
return bankNumS;
}
public void setBankNumS(ArrayList<BankNum> bankNumS) {
this.bankNumS = bankNumS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User() {
}
public User(String name) {
this.name = name;
}
}
class CardNum extends BankNum{
private String num;
private String passWord = "88888888";
public CardNum() {
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public CardNum(String num) {
this.num = num;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
}
class ATM{
private String num;
public ATM() {
}
public ATM(String num) {
this.num = num;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
}
2.nchu-software-oop-9
实话实说,这道题因为某些人为因素(会在踩坑心得中细说),我进行了两次重写,也是我认为这个学期中我最用心也是将面向对象的思维运用的最好的一次。
相比作业八,我增加了一些类,并且修改了已有类中的一些方法:

| Main | Bank | Account | Abstract Card | User | ATM | BankUnion | CreditCard | DebitCard | Test | Check | Transfer |
| 主类 | 银行类 | 银行账户类 | 抽象卡类 | 用户类 | ATM机类 | 银联类 | 信用卡类 | 借记卡类 | 初始化测试类 | 检测类 | 金额划转类 |
这道题因为跨行以及信用卡的出现,使得计算以及判断上会比作业八复杂一些,同时也便不能生搬硬套作业八中我的那种多重if嵌套检测的方法。
最终主类被我简化为:
作业九Main
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Check check = new Check();
Test test = new Test();
Transfer transfer = new Transfer();
String inform = input.nextLine();
while (!inform.equals("#"))
{
String []s = inform.split("\\s+");
Card card = check.checkCard(s, test.getBankUnion());
if (s.length == 1)
{
System.out.printf("业务:查询余额 ¥%.2f",card.getAccount().getMoney());
inform = input.nextLine();
continue;
}
check.checkPassword(s, card);
ATM atm = check.checkATM(s, test.getBankUnion());
if (check.checkMoney(s))
transfer.deposit(card,s,atm);
else
transfer.withdraw(card,s,atm);
inform = input.nextLine();
}
}
}
将除了分割字符串以及判定输出结束的过程都放到了两个加工类中,大大的减少了重复代码的出现,增加了空间利用率。
划转类和检测类
class Check{ //检测类
public Card checkCard(String []strings,BankUnion bankUnion){ //检测卡存在
Card card = null;
find:for (int i = 0; i < bankUnion.getBanks().size(); i++)
{
for (int j = 0; j < bankUnion.getBanks().get(i).getAccounts().size(); j++)
{
for (int k = 0; k < bankUnion.getBanks().get(i).getAccounts().get(j).getCards().size(); k++)
{
if (bankUnion.getBanks().get(i).getAccounts().get(j).getCards().get(k).getCount().equals(strings[0]))
{
card = bankUnion.getBanks().get(i).getAccounts().get(j).getCards().get(k);
break find;
}
}
}
}
if (card == null)
{
System.out.println("Sorry,this card does not exist.");
System.exit(0);
}
return card;
}
public ATM checkATM(String []strings, BankUnion bankUnion){ //检测ATM存在
ATM atm = null;
check:
for (int i = 0; i < bankUnion.getBanks().size(); i++)
{
for (int j = 0; j < bankUnion.getBanks().get(i).getAtms().size(); j++)
{
if (bankUnion.getBanks().get(i).getAtms().get(j).getName().equals(strings[2]))
{
atm = bankUnion.getBanks().get(i).getAtms().get(j);
break check;
}
}
}
if (atm == null)
{
System.out.println("Sorry,the ATM's id is wrong.");
System.exit(0);
}
return atm;
}
public boolean crossBank(ATM atm, Card card){ //检测是否跨行
return atm.getBank().equals(card.getAccount().getBank());
}
public void checkPassword(String []strings, Card card){ //检测密码正确
if (!strings [1].equals(card.getPassword()))
{
System.out.println("Sorry,your password is wrong.");
System.exit(0);
}
}
public boolean checkMoney(String []strings){ //检测存款或取款
return Double.parseDouble(strings[3]) < 0;
}
}
class Transfer{ //划转类
Check check = new Check();
public void deposit(Card card,String []strings,ATM atm) //存款方法
{
double money = -Double.parseDouble(strings[3]);
card.getAccount().setMoney(card.getAccount().getMoney() + money);
System.out.println("业务:存款 " + card.getAccount().getUser().getName() +
"在" + atm.getBank().getName() + "的"+atm.getName() + "号ATM机上存款¥" + String.format("%.2f",money));
System.out.printf("当前余额为¥%.2f\n",card.getAccount().getMoney());
}
public void withdraw(Card card,String []strings,ATM atm) //取款方法
{
double money = Double.parseDouble(strings[3]);
double saved = card.getAccount().getMoney();
if (card.getName().equals("借记卡")) //以下为借记卡
{
if (!check.crossBank(atm, card)) //跨行
{
if (saved - money * (1 + atm.getBank().getProcedures()) >= 0) //跨行,不透支
{
card.getAccount().setMoney(saved - money * (1 + atm.getBank().getProcedures()));
output(card,atm,money);
}
else
error();
}
else //不跨行
{
if (saved - money >= 0) //不跨行,不透支
{
card.getAccount().setMoney(saved - money);
output(card,atm,money);
}
else
error();
}
}
else //为信用卡
{
if (saved >= 0) //本金大于0
{
if (!check.crossBank(atm,card)) //跨行
{
if (saved - money >= 0) //不透支,跨行
card.getAccount().setMoney(saved - money * (1 + atm.getBank().getProcedures()));
else //透支,跨行
{
if (saved - money * (1 + atm.getBank().getProcedures()) - (money - saved) * 0.05 >= -50000)
card.getAccount().setMoney(saved - money * (1 + atm.getBank().getProcedures()) - (money - saved) * 0.05);
else
error();
}
output(card,atm,money);
}
else //不跨行
{
if (saved - money >= 0) //不透支,不跨行
card.getAccount().setMoney(saved - money);
else //透支,不跨行
{
if (saved - money - (money - saved) * 0.05 >= -50000)
card.getAccount().setMoney(saved - money - (money - saved) * 0.05);
else
error();
}
output(card,atm,money);
}
}
else //本金小于0
{
if (!check.crossBank(atm,card)) //跨行
{
if (saved - money * (1 + atm.getBank().getProcedures()) - money * 0.05 >= -50000) //透支,跨行
{
card.getAccount().setMoney(saved - money * (1 + atm.getBank().getProcedures()) - money * 0.05);
output(card,atm,money);
}
else
error();
}
else //不跨行,透支
{
if (saved - money * 1.05 >= -50000)
{
card.getAccount().setMoney(saved - money * 1.05);
output(card, atm, money);
}
else
error();
}
}
}
}
public void error(){ //超额错误方法
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
public void output(Card card, ATM atm, double money){ //取款输出方法
System.out.println("业务:取款 " + card.getAccount().getUser().getName() +
"在" + atm.getBank().getName() + "的"+atm.getName() + "号ATM机上取款¥" + String.format("%.2f",money));
System.out.printf("当前余额为¥%.2f\n",card.getAccount().getMoney());
}
}
然后就是我重新思考了类之间的关系,发现大多数都是有较强的关系,可以使用聚合的方法,比如:
聚合
//初始化银行账户数据
private Account account1 =new Account("3217000010041315709",YangGuo,CCB);
private Account account2=new Account("3217000010041315715",YangGuo,CCB);
private Account account3=new Account("3217000010051320007",GuoJing,CCB);
private Account account4=new Account("3222081502001312389",ZhangWuJi,ICBC);
private Account account5=new Account("3222081502001312390",ZhangWuJi,ICBC);
private Account account6=new Account("3222081502001312399",ZhangWuJi,ICBC);
private Account account7=new Account("3222081502051320785",WeiXiaoBao,ICBC);
private Account account8=new Account("3222081502051320786",WeiXiaoBao,ICBC);
private Account account9=new Account("3640000010045442002",ZhangSanFeng,CCB);
private Account account10=new Account("3640000010045441009",LingHuChong,ICBC);
private Account account11=new Account("3630000010033431001",QiaoFeng,ABC);
private Account account12=new Account("3630000010033431008",HongQiGong,ABC);
//初始化银行卡数据
private DebitCard card1 =new DebitCard("6217000010041315709",account1);
private DebitCard card2=new DebitCard("6217000010041315715",account1);
private DebitCard card3=new DebitCard("6217000010041315718",account2);
private DebitCard card4=new DebitCard("6217000010051320007",account3);
private DebitCard card5=new DebitCard("6222081502001312389",account4);
private DebitCard card6=new DebitCard("6222081502001312390",account5);
private DebitCard card7=new DebitCard("6222081502001312399",account6);
private DebitCard card8=new DebitCard("6222081502001312400",account6);
private DebitCard card9=new DebitCard("6222081502051320785",account7);
private DebitCard card10 =new DebitCard("6222081502051320786",account8);
private CreditCard card11=new CreditCard("6640000010045442002",account9);
private CreditCard card12=new CreditCard("6640000010045442003",account9);
private CreditCard card13=new CreditCard("6640000010045441009",account10);
private CreditCard card14=new CreditCard("6630000010033431001",account11);
private CreditCard card15=new CreditCard("6630000010033431008",account12);
针对本题的信用卡和借记卡的区分问题,我的方法是将原来的card类变为一个抽象类,然后产生其子类,name分别为“信用卡”以及“借记卡”。(实际上也可以用银行账户进行区分,但是我认为什么什么卡念起来更舒服所以采用了卡来区分)
DebitCard与CreditCard
abstract class Card{
private String name;
private String count;
private String password = "88888888";
private Account account;
public String getCount() {
return count;
}
public void setCount(String count) {
this.count = count;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public Card(String count,Account account) {
this.count = count;
this.account = account;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class DebitCard extends Card{ //借记卡
public DebitCard(String count,Account account){
super(count,account);
setName("借记卡");
}
}
class CreditCard extends Card{ //信用卡
public CreditCard(String count,Account account){
super(count,account);
setName("信用卡");
}
}
3、踩坑心得
1.随着代码的逐渐复杂,功能的逐渐繁多,老师对代码空间利用率的要求不断提高,面向对象思维的重要性逐渐提现了出来。特别是在作业九中,我第一次是在作业八的面向过程思维的主类的基础上进行的改进,最终导致了大量的相似代码出现,整个代码显得极其的累赘而臃肿。在我用面向对象的思维分化了各种功能并且加上足够的注释后,整体也就显得十分的清晰而且具有较高的可读性和复用性,适应了未来可能出现的更加的复杂的功能。
2.还是老生常谈的问题,写代码一定要仔细而且小心,特别是在像第九或者第八次这种由我们初始化而不是自定义输入的时候。我就因为Test类中初始化ATM时出现了少增加农行的一个ATM的问题,导致我的3个测试点一直过不去,最后还是在室友的帮助下发现了这个问题,不然我还真不会相信我抄都能抄错来(
3.依然是关于空间利用率的问题,在我这一道题中我就有两道题因为炸空间而提交不了。所以我思考了一下如何提高代码的简并性:使用更多的类以及方法分化各种反复需要使用的功能,减少相似代码的多次出现;可以在构造函数中进行修改且无需再次修改的就不用set与get,而是在构造函数中初始化。
4、改进建议
1.作业七中可以把这段代码也放到图形自己的类中进行,可以增加一定的复用性。

2.compareto方法没有被使用到,可以将比较大小的方法和compareto和在一起

3.第七次作业中的注释不够完备,在写文章的时候又仔细看了一遍才想起来要写注释。
4.第八次作业的思路需要改为面向对象思维。
5.第九次作业中有更多的可聚合的东西,可以减少一定的代码数量。
5、总结
在这三次作业中,我学会了:
1.面向对象的一些优点(结合上课知识):易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护。
2.在编码的时候一定要注意细节,不能完全依赖于idea的纠错。
3.提高自己的代码的简洁度,尽量使用面向对象的思维,将多重重复或者相似的方法进行整合。
这个学期下来我对老师的教学质量还是比较满意的,但是还是希望在课后能有更多的时间与学生进行交流,感谢老师这个学期的培养。
浙公网安备 33010602011771号