第三次blog作业
前言
从这三次题目集的情况来看,考察的知识点包括以下(第七次作业:掌握类的继承、多态性使用方法以及接口的应用;第八次:它重点考核类的封装性及类间关系设计(关联、组合及依赖);第九次作业:他的重点训练内容为抽象类、继承与多态)。
题量相对于之前的几次题目集作业是较大的,难度相对于之前也有很大的提高,要想消化理解并完全转化为己用,还是需要非一些时间的,但是我认为只要通过不懈的认真努力,我相信没有什么是解决不了的问题。
设计与分析
(1) 先分析题目集七的一些相关信息
第七次的圈复杂度来进行分析,图表如下

由上表可知,卡片排序的复杂度只有6,并不是很高,说明我的代码的可测性还是很高的,维护成本相对较低,满足了要求。
(7-1)根据powerdesigner所设计出来的类图

Comparable 接口的应用 图形类设计参考了作业 6-1 的类层次结构,此次作业要求对卡片排序时使用 Comparable 接口, 即 Card 类需要实现 Comparable 接口中的 CompareTo()方法。做这道题首先要能够迅速求出各卡片的面积大小,然后将卡片按照其面积值从大到小进行排序,同时求出所有卡片的面积之和,这就是本道题的全部思路。
(7-2)本题根据( 7-1),主要对卡片(Card)进行分组游戏,规则为随机发放一些卡片给学生, 卡片仍然分为四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid), 并给出各种卡片的相应参数,首先我们要根据卡片类型将所有卡片进行分组(一个类型分为一组, 所以最多四组),然后能够对每组内的卡片根据面积值从大到小进行排序,同时求出该组内所有卡片 的面积之和,最后只需再求出每组卡片面积之和中的最大值即可。 还有一点,Comparable、Comparator 接口的应用 、图形类设计我参考了作业 7-1 的类层次结构,但我们需要进一步进行完善总结。因为本次作业要求对卡片排序时使用 Comparable 接口或 Comparator 接口。所以对程序功能的需求以及实现功能 、 对各图形信息进行输入并输出、入数据的正确性校验、对输入的图形按照图形类型进行分组都要进行全面的完善。类图同上,在这里不过多介绍。
(2)ATM(一)
本次作业我们对程序功能需求有实现功能基础数据的初始化、用户存款、取款及查询余额功能、初始化数据等一系列的工作需要进行。现将本次的类图奉上。

由类图不难分析出类与类之间的关系。
首先应该搞清楚,这些类文件中之间的关系,每个类之间需要用到什么样的方法;那么我们先填写Account类,之后填写信用账户类CreditAccount;我们应该明白,他是继承Account类的,但是,他又需要拥有自身独立的属性,我们可以添加一个最高透支额度的属性,最重要的是填写Bank类的内容,在这个类中,我们要完成注册,产生银行账户,统计所有信用账户的最高透支额度的总和,统计所有账户的总余额, 查询出所有信用账户中透支额度最高的账户, 查询出所有储蓄账户中余额最高的账户等功能,用这样的方法来实现代码。
ATM(二)
这次的作业,在老师的代码基础之上,进行修改。我们务必注意本题目中的各实体类之间的关系,尤其是一对多的组合关系。在对实体类的设计要做到单一职责原则,且不能缺少规定的实体类。要实现的功能还是基础数据的初始化以及用户取款及查询余额等功能。本题代码如下

我们只需要改个account为抽象类,让他变成两个类,分别是贷记账户和借机账户,并且我们要针对不同的账户有不同的取钱方式即可。本题的思路其实和上一道题目差不多,都需要要完成注册,产生银行账户,统计所有信用账户的最高透支额度的总和,统计所有账户的总余额, 查询出所有信用账户中透支额度最高的账户, 查询出所有储蓄账户中余额最高的账户等功能来实现代码。
采坑心得
在做第一道题的过程中,避免不了多次的debug,首先要考虑每个测试点是否能够通过,就拿第七次作业来说,在使用arraylist和数组时,我们要明白他的区别在哪里,一旦我们创建了一个数组,那么它的大小就固定了。当创建Aeeaylist后,如果元素不在数组列表中,就不能使用get,set方法。并且向数组列表中添加、插入和删除元素是比较容易的。
ArrayList<int> 1istOfIntegers = new ArrayList<>();
这样的答案是行的,这样行不通,因为存储在Arraylist中的元素必须是一种对象。不能使用像int的基本数据类型来代替一个泛型类型。然而,可以创建一个存储Integer对象的ArrayList,如下所示:
ArrayList<Integer> 1istOfIntegers = new ArrayList<>();
注意remove(int index)方法移除指定下标位置的元素。要从1istOfIntegers中移除一个整数值,需要使用list0fIntegers.remove(new Integer(v))。这不是一个好的Java API设计,因为容易导致错误。将remove(int)改名为removeAt(int)会更好。
public class Main{
public static Scanner cy = new Scanner(System.in);
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<Integer>();
int n = cy.nextInt();
while(n!=0){
if(n<0||n>4){
System.out.println("Wrong Format");
System.exit(0);
}
list.add(n);
n=cy.nextInt();
}
DealCardList dealCardList = new DealCardList(list);
if(!dealCardList.validate()){
System.out.println("Wrong Format");
System.exit(0);
}
dealCardList.showResult();
cy.close();
}
}
其次我想说的是,ATM系统相关的内容,此次作业的题目量较上次而言相对较大,内容较难,atm用到的是封装性及其接口的使用,首先我们要按照题目的要求一一的去解答此类问题。首先应该搞清楚,这些类文件中之间的关系,每个类之间需要用到什么样的方法;而不是盲目的瞎找瞎做,那么我们先填写Account类,之后填写信用账户类CreditAccount;我们应该明白,他是继承Account类的,但是,他又需要拥有自身独立的属性,代码奉上。
class Account {
private String accountNO;
private double balance = 0;
private User user = null;
private Bank bank = null;
private static ArrayList<Card> list = new ArrayList<Card>();
public Account() {
super();
// TODO Auto-generated constructor stub
}
public Account(String accountNO, double balance, User user, Bank bank) {
super();
this.accountNO = accountNO;
this.balance = balance;
this.user = user;
this.bank = bank;
}
public void addCard(Card card) {
list.add(card);
}
public void removeCard(Card card) {
list.remove(card);
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getAccountNO() {
return accountNO;
}
public void setAccountNO(String accountNO) {
this.accountNO = accountNO;
}
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 ArrayList<Card> getList() {
return list;
}
public void setList(ArrayList<Card> list) {
Account.list = list;
}
public static Account getAmountbyCardNO(String cardNO) {
Iterator<Card> cardItr = Account.list.iterator();
Card card = null;
while(cardItr.hasNext()) {
card = cardItr.next();
if(card.getCardNO().equals(cardNO)) {
return card.getAccount();
}
}
return null;
}
}
我们务必要注意本题目中的各实体类之间的关系,尤其是一对多的组合关系,当我们能完全的搞清楚状况之后,接着要对实体类的设计要做到单一职责原则,且不能缺少规定的实体类。再者编程时考虑面向对象中的封装性,本次题目中的应用以及有能够扩展的衍生需求。通过测试点报错的原因来仔细找到错误的根本原因。
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 = ValidateData.getATMbyATMID(unionPay, ATMID);
if(aTM == null) {
System.out.println("Sorry,the ATM's id is wrong.");
System.exit(0);
}
而这一步是为了验证校验ATM是否存在
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);
}
检验校验卡密码是否正确
校验取款金额是否大于余额
if (amount > balance) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
判断校验取款金额是否大于余额
取款更新余额操作
account.setBalance(balance - amount)
if(amount >= 0) {
showResult(account,1);
}else {
showResult(account,0);
}
}
检查校验是否为跨行取款
public void showResult(Account account,int flag) {
String type = "";
if(flag == 1) {
type = "取款";
}else {
type = "存款";
amount *= -1;
}
String userName = account.getUser().getName();
String bankName = account.getBank().getBankName();
System.out.println("业务:"+ "取款 " +userName + "在" +
bankName + "的" + ATMID + "号ATM机上" +type + String.format("¥%.2f", amount));
System.out.print("当前余额为" + String.format("¥%.2f", account.getBalance()));
}
}
class ValidateData {
/**
* 校验卡号是否存在
* @param unionPay
* @param cardNO
* @return
*/
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;
}
}
改进建议
我觉得在写代码的时候,应该要代码中实现不同功能的部分用空行隔开,并且在前面都有对本段功能描述的注释语句,这样能够更加地清晰易懂。
其次整齐的缩进会使得代码条理清楚,整洁易读;空格是首选的缩进方式,制表符只能用于与同样使用制表符缩进的代码保持一致。
续行应该与其包裹元素对齐,要么使用圆括号、方括号和花括号内的隐式行连接来垂直对齐,要么使用挂行缩进对齐;当使用挂行缩进时,应该考虑到第一行不应该有参数,以及使用缩进以区分自己是续行;每行最大长度79,换行可以使用反斜杠,换行点要在操作符的后边敲回车。
再者我们的命名也应该规范有序,比如各种右括号前不要加空格;逗号、冒号、分号前不要加空格。这是一个程序员所应该具备的各项要求,写代码时应该极力地向这方面发展。
总结
通过这几次的学习和了解,我掌握了列表的一些有用方法,Java它本身也提供给了一些方法,用于从数组创建列表等等。我还了解到为了重写一个方法,必须使用与它的父类中的方法一样的签名、一样或者兼容的返回类型来定义子类中的方法。并且实例方法只有在可访问时才能重写。这样,私有方法是不能重写的,因为它是不能在类本身之外访问的。如果子类中定义的方法在父类中是私有的,那么这两个方法是完全没有关系的。
我学到静态方法与实例方法一样可以继承。但是,静态方法不能重写,如果父类中定义的静态方法在子类中重新定义,那么父类中定义的方法可能会被隐藏。其实Java中的每个类都继承自java.lang.Object类。如果一个类在定义时没有指定继承关系,那么它的父类就是Object。
在Java中,接口被认为是一种特殊的类,并且还知道一个接口可以继承一个或多个接口,但一个类仅能进车给一个父类,但却可以实现一个或多个接口。即使父类是具体的,子类也可以是抽象的等等一系列的相关知识。但这些仅仅只是些皮毛,多上上网查一些复习资料,帮助自己去巩固和提高。抽象类和常规类是一样的,都有数据和方法,但是他们都不能用new操作符创建抽象类的实例。
在课上我觉得老师讲的很好,有很好的引导作用,并且老师讲话也比较生动幽默,课堂上的氛围很好,对于这几次的作业,他的量正正好好,对于我们来说即能很有效,有很好的贯彻老师他该有的教育体系,我觉得很好,没什么问题,希望老师能够更好地去磨炼和提高自己,对学生的管控能更加合理,教学方式能更加多样,其他的没什么了,这就是我所要说的。
浙公网安备 33010602011771号