Banking系统
- 开发前的话:
- Banking系统是校验初级程序员对Java语言特性的最佳实践项目,该项目分成八个设计阶段,每个阶段都在考量码哥对Java语言特性的熟练度。每个阶段说明都十分详细,初学者一定要基于"每个阶段的说明"去一步步去实现,实现过程中做到不超纲,不放水。免得庞大的代码量把自己绕成一个傻Ber...待到完成任务,就可以根据最终的实现结果回溯自己的不足。(记住:即使把编程语言的特性倒背如流也无法成为真正的专家,成为专家前需要不断模仿,从模仿中提炼自己思考问题的方式)。
- 实现过程
- 第一阶段
- 您是否会创建一个简单的"银行程序包"?
- 您是否对Java语言中面向对象特性及构造器的创建和使用知之甚详?
- 第二阶段
- 您是否知道如何使用”引用类型的成员变量"?
- 您是如何思考类间的组合关系?
- 第三阶段
- 您是否会使用或定义带有返回值类型的方法?
- 第四阶段
- 您是否会使用数组,以及区别数组与集合?
- 第五阶段
- 您是否理解面向对象的三大特性:继承?多态?以及方法的重写?
- 第六阶段
- 第七阶段
- 第八阶段
- 第一阶段
- 项目总结
第一阶段:
实验题目 1: 创建一个简单的银行程序包 实验目的: Java 语言中面向对象的封装性及构造器的创建和使用。 实验说明: 在这个练习里,创建一个简单版本的 Account 类。将这个源文件放入 banking 程序包中。在创建单个帐户的默认程序包中,已编写了一个测试程序 TestBanking。 这个测试程序初始化帐户余额,并可执行几种简单的事物处理。最后,该测试程 序显示该帐户的最终余额。 提示: 1.创建 banking 包 2. 在 banking 包下创建 Account 类。该类必须实现上述 UML 框图中的模型。 a. 声明一个私有对象属性:balance,这个属性保留了银行帐户的当前(或 即时)余额。 b. 声明一个带有一个参数( init_balance ) 的公有构造器, 这个参数为 balance 属性赋值。 c. 声明一个公有方法 geBalance,该方法用于获取经常余额。 d. 声明一个公有方法 deposit,该方法向当前余额增加金额。 e. 声明一个公有方法 withdraw 从当前余额中减去金额。 3.打开TestBanking.java文件,按提示完成编写,并编译 TestBanking.java 文件。 4. 运行 TestBanking 类。可以看到下列输出结果: Creating an account with a 500.00 balance Withdraw 150.00 Deposit 22.50 Withdraw 47.62 The account has a balance of 324.88
- entity
- Account.java
package entity; public class Account { /** * balance:当前账户余额 */ private double balance; /** * */ public Account() { balance = 0; } /** * * @param balance */ public Account(double balance) { this.balance = balance; } /** * bean */ public double getBalance() { return balance; } /** * */ public double deposit(double amt) { if(amt>10000){ System.out.println("存款额度不得大于1万"); }else{ System.out.println("存款成功" ); return balance = balance + amt; } return balance; } /** * 取款事务说明: * 1.balance=0时,不允许取款 * 2.balance!=0时 * 2.1 amt>balance时,不允许取款 * 2.2 amt<=balance时 ,返回取款后的余额 * * @param amt * @return */ public double withdraw(double amt) { if (balance != 0) { if (amt > balance) { System.out.println("余额不足,取款失败"); } else { System.out.println("取款成功"); return balance = balance - amt; } } else System.out.println("取款失败"); return balance; } }
- Account.java
第二阶段:
阶段二: 扩展银行项目,添加一个 Customer 类。Customer 类将包含一个 Account对象。 实验目的:使用引用类型的成员变量 提示: 1. 在banking包下的创建Customer类。该类必须实现上面的UML图表中的模型。 a. 声明三个私有对象属性:firstName、lastName 和 account。 b. 声明一个公有构造器,这个构造器带有两个代表对象属性的参数(f 和 l) c. 声明两个公有存取器来访问该对象属性,方法 getFirstName 和 getLastName 返 回相应的属性。 d. 声明 setAccount 方法来对 account 属性赋值。 e. 声明 getAccount 方法以获取 account 属性。 2. 在 exercise2 主目录里,编译运行这个 TestBanking 程序。应该看到如下输出结果: Creating the customer Jane Smith. Creating her account with a 500.00 balance. Withdraw 150.00 Deposit 22.50 Withdraw 47.62 Customer [Smith, Jane] has a balance of 324.88
- entity
- Account.java
-
package entity; public class Account { /** * balance:当前账户余额 */ private double balance; /** * */ public Account() { balance = 0; } /** * * @param balance */ public Account(double balance) { this.balance = balance; } /** * bean */ public double getBalance() { return balance; } /** * */ public double deposit(double amt) { if(amt>10000){ System.out.println("存款额度不得大于1万"); }else{ System.out.println("存款成功" ); return balance = balance + amt; } return balance; } /** * 取款事务说明: * 1.balance=0时,不允许取款 * 2.balance!=0时 * 2.1 amt>balance时,不允许取款 * 2.2 amt<=balance时 ,返回取款后的余额 * * @param amt * @return */ public double withdraw(double amt) { if (balance != 0) { if (amt > balance) { System.out.println("余额不足,取款失败"); } else { System.out.println("取款成功"); return balance = balance - amt; } } else System.out.println("取款失败"); return balance; } }
- Customer.java
package entity; public class Customer { /** * 客户属性 */ private Account account; // private String firstName; private String lastName; /** * */ public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public Customer() { // TODO Auto-generated constructor stub } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public Account getAccount(){ return new Account(); } public void setAccount(Account account){ this.account=account; } @Override public String toString(){ return firstName+" | "+lastName; } }
第三阶段:
实验题目 3: 修改 withdraw 方法以返回一个布尔值,指示交易是否成功。 实验目的:使用有返回值的方法。 :修改 Account 类 :修改 deposit 方法返回 true(意味所有存款是成功的)。 :修改 withdraw 方法来检查提款数目是否大于余额。如果 amt 小于 balance, 则从余额中扣除提款数目并返回 true,否则余额不变返回false。 : 测试 Creating the customer Jane Smith. Creating her account with a 500.00 balance. Withdraw 150.00: true Deposit 22.50: true Withdraw 47.62: true Withdraw 400.00: false Customer [Smith, Jane] has a balance of 324.88
- entity
- Account.java
-
package entity; /** * 第三阶段修改处:”*“基于上阶段修改处的标记 * @author doublezi * */ public class Account { /** * balance:当前账户余额 */ private double balance; /** * */ public Account() { balance = 0; } /** * * @param balance */ public Account(double balance) { this.balance = balance; } /** * bean */ public double getBalance() { return balance; } //* public boolean deposit(double amt) { if(amt>10000){ System.out.println("存款额度不得大于1万"); }else{ balance=balance+amt; System.out.println("存款成功" ); return true;//* } return false;//* } /** * 取款事务说明:(第三阶段) * getBalance():当前账户余额 * 1. getBalance()>amt : false * 2. 反之: 更新账户余额 * * * @param amt * @return */ //* public boolean withdraw(double amt) { if(getBalance()<amt){ return false;//* }else{ balance=balance-amt; System.out.println("取款成功"); return true;//* } } }
- Customer.java
-
package entity; public class Customer { /** * 客户属性 */ private Account account; // private String firstName; private String lastName; /** * */ public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public Customer() { // TODO Auto-generated constructor stub } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public Account getAccount(){ return new Account(); } public void setAccount(Account account){ this.account=account; } @Override public String toString(){ return firstName+" | "+lastName; } }
第四阶段:
第四阶段说明
实验题目 4: 将用数组实现银行与客户间的多重关系。 实验目的:在类中使用数组作为模拟集合操作。 对银行来说,可添加 Bank 类。 Bank 对象跟踪自身与其客户间的关系。用 Customer 对象的数组实现这个集合化的关系。还要保持一个整数属性来跟踪银 行当前有多少客户。 a. 创建 Bank 类 b. 为 Bank 类 增 加 两 个 属 性 : customers(Customer对象的数组 ) 和numberOfCustomers(整数,跟踪下一个 customers 数组索引) c. 添加公有构造器,以合适的最大尺寸(至少大于 5)初始化 customers 数组。 d. 添加 addCustomer 方法。该方法必须依照参数(姓,名)构造一个新的 Customer 对象然后把它放到 customer 数组中。还必须把 numberofCustomers 属性的值加 1。 e. 添加 getNumOfCustomers 访问方法,它返回 numberofCustomers 属 性值。 f. 添加 getCustomer方法。它返回与给出的index参数相关的客户。 g. 编译并运行 TestBanking 程序。可以看到下列输出结果: Customer [1] is Simms,Jane Customer [2] is Bryant,Owen Customer [3] is Soley,Tim Customer [4] is Soley,Maria
- entity
- Account.java
-
package entity; /** * 第三阶段修改处:* * @author doublezi * */ public class Account { /** * balance:当前账户余额 */ private double balance; /** * */ public Account() { balance = 0; } /** * * @param balance */ public Account(double balance) { this.balance = balance; } /** * bean */ public double getBalance() { return balance; } //* public boolean deposit(double amt) { if(amt>10000){ System.out.println("存款额度不得大于1万"); }else{ balance=balance+amt; System.out.println("存款成功" ); return true;//* } return false;//* } /** * 取款事务说明:(第三阶段) * getBalance():当前账户余额 * 1. getBalance()>amt : false * 2. 反之: 更新账户余额 * * * @param amt * @return */ //* public boolean withdraw(double amt) { if(getBalance()<amt){ return false;//* }else{ balance=balance-amt; System.out.println("取款成功"); return true;//* } } }
- Customer.java
-
package entity; public class Customer { /** * 客户属性 */ private Account account; // private String firstName; private String lastName; /** * */ public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public Customer() { // TODO Auto-generated constructor stub } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public Account getAccount(){ return new Account(); } public void setAccount(Account account){ this.account=account; } @Override public String toString(){ return firstName+" | "+lastName; } }
- Bank.java
-
package entity; public class Bank { private Customer customers[]; private int noOfCustomers[]; public static int count = 0; public static int index = 0; public Bank() { customers = new Customer[5]; noOfCustomers = new int[5]; } public void addCustomer(String firstName, String lastName) { index = +count; // 区别:对于计数器和索引器,使用静态变量和局部变量的区别 customers[index] = new Customer(firstName, lastName); noOfCustomers[index] = (++count); } public int getNoOfCustomers() { return noOfCustomers.length; } public int getNoCustomers(int index) { return noOfCustomers[index]; } public Customer getCustomer(int index) { return customers[index]; } }
第五阶段:
实验题目 5: 在银行项目中创建 Account 的两个子类:SavingAccount 和 CheckingAccount 实验目的:继承、多态、方法的重写。 提 示: 创建 Account 类的两个子类:SavingAccount 和 CheckingAccount 子类 a. 修改 Account 类;将 balance 属性的访问方式改为 protected b. 创建 SavingAccount 类,该类继承 Account 类 c. 该类必须包含一个类型为 double 的 interestRate 属性 d. 该类必须包括带有两个参数(balance 和 interest_rate)的公有构造器。该构造器必须通过调用 super(balance)将 balance 参数传递给父类构造器。 实现 CheckingAccount 类 1. CheckingAccount 类必须扩展 Account 类 2. 该类必须包含一个类型为 double 的 overdraftProtection 属性。 3. 该类必须包含一个带有参数(balance)的共有构造器。该构造器必须通过调用 super(balance)将 balance 参数传递给父类构造器。 4. 给类必须包括另一个带有两个参数(balance 和 protect)的公有构造器。该 构造器必须通过调用 super(balance)并设置 overdragtProtection 属性,将 balance 参数传递给父类构造器。 5. CheckingAccount 类必须覆盖 withdraw 方法。此方法必须执行下列检查。如 果当前余额足够弥补取款 amount,则正常进行。如果不够弥补但是存在透支 保护,则尝试用 overdraftProtection 得值来弥补该差值 (balance-amount). 如果弥补该透支所需要的金额大于当前的保护级别。则整个交易失败,但余 额未受影响。 6. 在主 exercise1 目录中,编译并执行 TestBanking 程序。输出应为: Creating the customer Jane Smith. Creating her Savings Account with a 500.00 balance and 3% interest.
- entity
- Account.java
-
package entity; /** * 第三阶段修改处:flag=* * @author doublezi * */ public class Account { /** * balance:当前账户余额 */ protected double balance; /** * */ public Account() { balance = 0; } /** * * @param balance */ public Account(double balance) { this.balance = balance; } /** * bean */ public double getBalance() { return balance; } /** * */ //* public boolean deposit(double amt) { if(amt>10000){ System.out.println("存款额度不得大于1万"); }else{ balance=balance+amt; System.out.println("存款成功" ); return true;//* } return false;//* } /** * 取款事务说明:(第三阶段) * getBalance():当前账户余额 * 1. getBalance()>amt : false * 2. 反之: 更新账户余额 * * * @param amt * @return */ //* public boolean withdraw(double amt) { if(getBalance()<amt){ return false;//* }else{ balance=balance-amt; System.out.println("取款成功"); return true;//* } } }
- Bank.java
-
package entity; public class Bank { private Customer customers[]; private int noOfCustomers[]; public static int count = 0; public static int index = 0; public Bank() { customers = new Customer[5]; noOfCustomers = new int[5]; } public void addCustomer(String firstName, String lastName) { index = +count; // 区别:对于计数器和索引器,使用静态变量和局部变量的区别 customers[index] = new Customer(firstName, lastName); noOfCustomers[index] = (++count); } public int getNoOfCustomers() { return noOfCustomers.length; } public int getNoCustomers(int index) { return noOfCustomers[index]; } public Customer getCustomer(int index) { return customers[index]; } }
- Customer
-
package entity; public class Customer { /** * 客户属性 */ private Account account; // private String firstName; private String lastName; /** * */ public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public Customer() { // TODO Auto-generated constructor stub } public String getFirstName(){ return firstName; } public String getLastName(){ return lastName; } public Account getAccount(){ return new Account(); } public void setAccount(Account account){ this.account=account; } @Override public String toString(){ return firstName+" | "+lastName; } }
- CheckingAccount.java(extends Account)
-
package entity; import java.util.Scanner; /** * Checking Account:普通支票账户-->无息 特点:可以免费多次存取现金,无利息 * * @author doublezi * */ public class CheckingAccount extends Account { /** * 透支额度 */ private double overDraftProtection; public double getOverDraftProtection() { if (balance >= 0 && balance <= 1000) { return overDraftProtection = 100; } if (balance > 1000 && balance <= 5000) { return overDraftProtection = 500; } if (balance > 5000 && balance <= 10000) { return overDraftProtection = 700; } return -1; } /** * */ public CheckingAccount() { balance = Math.random() * 10000; } public CheckingAccount(double balance) { this.balance = balance; } public CheckingAccount(double balance, double overDraftProtection) { super(balance); this.overDraftProtection = overDraftProtection; } @Override public double getBalance() { return balance; } @Override public boolean withdraw(double amt) { if (balance-amt>0) { balance = balance - amt; System.out.println("余额:" + balance); return true; } else { // 获取可透支额度 if(amt==balance+getOverDraftProtection()){ System.out.println("Checking Account:"+(balance-amt)); }else // 获取透支后余额 System.out.println("请在可透支范围内提款!"); return true; } } @Override public String toString() { return "Checking Account:" + balance + "$ , 可透支额度为:" + this.getOverDraftProtection()+ "$"; } }
- SavingAccount.java(extends Account)
-
package entity; /** * Saving Account:活期储蓄账户-->有固定利率 特点:存放在Saving Account的钱,通常一个月可以有有限次数提款 * 假定每月限制仅能提款一次,超过提款次数限制,则收取手续费(30¥) * * @author doublezi * */ public class SavingAccount extends Account { /** * 利率: interest Rate */ private double interestRate; public SavingAccount() { } public SavingAccount(double balance, double interestRate) { super(balance); this.balance = balance; } /** * * @param a * @param amt * @return */ public double saveTactics(Account a, double amt) { return 0; } @Override public String toString() { return "Saving Account:" + balance + "¥"; } }
第五阶段扩展:
创建客户账户: 说明---实际生活中,我们所有持有某个特定银行中的多张银行卡,具体卡有没有钱那hi另一回事了。所以当设计一个客户拥有多个账户时,是合乎情理的,符合实际情况 实验目的: instanceof 运算符的应用 提 示: 修改 Customer 类 1. 修改 Customer 类来处理具有多种类型的联合账户。 (例如用数组表示多重性一节所作的,该类必须包括以下的公有方法: addAccount(Account),getAccount(int)和 getNumOfAccounts()。 每个 Customer 可以有多个 Account。(声明至少有 5 个) 2. 完成 TestBanking 程序 该程序创建一个客户和账户的集合,并生成这些客户及其账户余额的报告。在 TestBanking.Java 文件中,你会发现注释块以/***…***/来开头和结尾。这 些注释只是必须提供的代码的位置。 3. 使用 instanceof 操作符测试拥有的账户类型,并且将 account_type 设置 为适当的值,例如:“SavingsAccount”或“CheckingAccount”。 4. 编译并运行该程序,将看到下列结果 ----------------------------------------------- 客户:客户名 持卡类型:定期储蓄账户,账户余额: ***¥ 持卡类型:活期储蓄账户,账户余额: ***¥ ------------------------------------------------ 注:关于"Checking Account"和"Saving Account"的区别: 一般“个人”在国外银行开设账户,依性质不同主要分为下列几种: 1)普通支票账户(Checking Account);一般无息 2)活期储蓄账户(Savings Account);一般固定利率 3)定期储蓄账户(Certificate of Deposit 简称 CD);固定利率 4)浮动利率账户(Money Market Account);也算活期储蓄账户的一种,但利率随行就市每日调整 一个是经常账户 checking account 根据所选的package 可以免费多次存取提取现金。 没有利息。 一个是储蓄账户 saving account。这个账户是有利息的。 但是这个一般钱放进去一个月只有有限的次数可以动,一般一个月一次,超过次数若要提取的话,根据账户种类会收不同额度的手续费,例如两块,或者五块。 CUSTOMERS REPORT ================ Customer: Simms, Jane Savings Account: current balance is ¥500.00 Checking Account: current balance is ¥200.00 Customer: Bryant, Owen Checking Account: current balance is ¥200.00 Customer: Soley, Tim Savings Account: current balance is ¥1,500.00 Checking Account: current balance is ¥200.00 Customer: Soley, Maria Checking Account: current balance is ¥200.00 Savings Account: current balance is ¥150.00
- entity
- Account.java
package entity; /** * 第三阶段修改处:flag=* * @author doublezi * */ public class Account { /** * balance:当前账户余额 */ protected double balance; /** * */ public Account() { balance = 0; } /** * * @param balance */ public Account(double balance) { this.balance = balance; } /** * bean */ public double getBalance() { return balance; } @Override public String toString(){ return "账户余额:"+balance; } /** * */ //* public boolean deposit(double amt) { if(amt>10000){ System.out.println("存款额度不得大于1万"); }else{ balance=balance+amt; System.out.println("存款成功" ); return true;//* } return false;//* } /** * 取款事务说明:(第三阶段) * getBalance():当前账户余额 * 1. getBalance()>amt : false * 2. 反之: 更新账户余额 * * * @param amt * @return */ //* public boolean withdraw(double amt) { if(getBalance()<amt){ return false;//* }else{ balance=balance-amt; System.out.println("取款成功"); return true;//* } } }
- Bank.java
package entity; public class Bank { private Customer customers[]; private int noOfCustomers[]; public static int count = 0; public static int index = 0; public Bank() { customers = new Customer[5]; noOfCustomers = new int[5]; } public void addCustomer(String firstName, String lastName) { index = +count; // 区别:对于计数器和索引器,使用静态变量和局部变量的区别 customers[index] = new Customer(firstName, lastName); noOfCustomers[index] = (++count); } public int getNoOfCustomers() { return noOfCustomers.length; } public int getNoCustomers(int index) { return noOfCustomers[index]; } public Customer getCustomer(int index) { return customers[index]; } }
- CheckingAccount.java(extends Account)
package entity; import java.util.Scanner; /** * Checking Account:普通支票账户-->无息 特点:可以免费多次存取现金,无利息 * * @author doublezi * */ public class CheckingAccount extends Account { /** * 透支额度 */ private double overDraftProtection; public double getOverDraftProtection() { if (balance >= 0 && balance <= 1000) { return overDraftProtection = 100; } if (balance > 1000 && balance <= 5000) { return overDraftProtection = 500; } if (balance > 5000 && balance <= 10000) { return overDraftProtection = 700; } return -1; } /** * */ public CheckingAccount() { balance = Math.random() * 10000; } public CheckingAccount(double balance) { this.balance = balance; } public CheckingAccount(double balance, double overDraftProtection) { super(balance); this.overDraftProtection = overDraftProtection; } @Override public double getBalance() { return balance; } @Override public boolean withdraw(double amt) { if (balance-amt>0) { balance = balance - amt; System.out.println("余额:" + balance); return true; } else { // 获取可透支额度 if(amt==balance+getOverDraftProtection()){ System.out.println("Checking Account:"+(balance-amt)); }else // 获取透支后余额 System.out.println("请在可透支范围内提款!"); return true; } } @Override public String toString() { return "Checking Account:" + balance + "$ , 可透支额度为:" + this.getOverDraftProtection()+ "$"; } }
- SavingAccount.java(extends Account)
package entity; /** * Saving Account:活期储蓄账户-->有固定利率 特点:存放在Saving Account的钱,通常一个月可以有有限次数提款 * 假定每月限制仅能提款一次,超过提款次数限制,则收取手续费(30¥) * * @author doublezi * */ public class SavingAccount extends Account { /** * 利率: interest Rate */ private double interestRate; public SavingAccount() { balance = Math.random() * 10000; } public SavingAccount(double balance, double interestRate) { super(balance); this.balance = balance; } /** * * @param a * @param amt * @return */ public double saveTactics(Account a, double amt) { return 0; } @Override public String toString() { return "Saving Account:" + balance + "¥"; } }
- CheckingAccount.java(extends Account)
- Costomer.java
package entity; public class Customer { /** * 客户属性 */ private Account account; // private String firstName; private String lastName; private Account accounts[]; private int noOfAccounts[]; public static int count = 0; //模拟账户编号(1,2,3,4,5) public static int index = 0; //模拟数组索引值(0,1,2,3,4) /** * */ public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; accounts = new Account[5]; noOfAccounts = new int[5]; } public Customer() { accounts = new Account[5]; noOfAccounts = new int[5]; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public Account getAccount() { return new Account(); } public void setAccount(Account account) { this.account = account; } @Override public String toString() { return firstName + " | " + lastName; } /** * 客户类自己的行为方法 1.通常一个客户可以拥有多个银行账户 */ public Account addAccount(Account a) { // 索引设计的准确性 index = +count; if (index % 2 == 0) { a = new CheckingAccount(); } else { a=new SavingAccount(); } accounts[index] = a; noOfAccounts[index] = (++count); return a; } public int getNoOfAccounts(int index) { return noOfAccounts[index]; } /** * 指定的索引存放着客户(Customer)不同的账户(Account) * * @param index * @return */ public Account getAccounts(int index) { return accounts[index]; } }
- Account.java