银行系统
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 85 课,共 87 课。
这个挑战要求你使用 OOP 原则构建一个模拟现实金融业务的银行系统。
你的系统应能处理不同类型的账户,例如 SavingsAccount 和 CheckingAccount,它们都继承自基础 Account 类。每种账户类型都有独特的行为:储蓄账户可能会赚取利息,而支票账户可能会提供透支保护。
想一想如何对交易进行建模。像 Transactable 这样的接口可以定义 deposit() 和 withdraw() 方法。可以考虑使用 InsufficientFundsException 等自定义异常,妥善处理无效操作。
Bank 类可以管理多个账户和客户,以此展示组合。你可以应用工厂模式来创建不同类型的账户,也可以使用观察者模式,在账户发生变化时通知客户。
重点学习封装,以保护余额和账号等敏感数据,并使用多态统一处理不同类型的账户。
挑战
简单让我们构建一个完整的银行系统,展示你对 OOP 原则的掌握!你将创建一个包含不同账户类型、交易处理和完善异常管理的系统,并将代码组织在多个文件中。
你将把代码组织在 7 个文件中:
Transactable.java:创建一个接口,用于定义金融操作的规范。它应声明方法deposit(double amount)和withdraw(double amount),两者都返回布尔值来表示操作是否成功。InsufficientFundsException.java:创建一个继承自Exception的自定义异常。构造函数应接收尝试取款的金额和当前余额,并按格式Insufficient funds: attempted [amount], available [balance]创建消息。Account.java:创建一个抽象基类,表示任意银行账户。添加accountNumber(String)和balance(double)两个私有字段、一个用于初始化这两个字段的构造函数、适当的 getter、一个受保护的余额 setter(以便子类可以修改余额),以及一个返回 String 的抽象方法getAccountType()。实现方法getDetails(),使其返回"[accountNumber] ([accountType]): $[balance]",其中余额保留 2 位小数。SavingsAccount.java:创建一个继承Account并实现Transactable的类。添加一个interestRate(double)私有字段。构造函数接收 accountNumber、初始余额和 interestRate。实现getAccountType(),使其返回"Savings"。对于deposit(),将金额加到余额上并返回 true。对于withdraw(),如果金额超过余额,则返回 false;否则扣除该金额并返回 true。添加方法applyInterest(),按balance * interestRate的值增加余额(利率以小数形式存储,因此0.05表示 5%)。CheckingAccount.java:创建一个继承Account并实现Transactable的类。添加一个overdraftLimit(double)私有字段。构造函数接收 accountNumber、初始余额和 overdraftLimit。实现getAccountType(),使其返回"Checking"。对于deposit(),将金额加到余额上并返回 true。对于withdraw(),如果金额小于或等于余额加 overdraftLimit,则允许取款;如果金额超过此限额,则返回 false。Bank.java:创建一个使用 ArrayList 管理账户的类。添加以下方法:addAccount(Account account):将账户添加到银行findAccount(String accountNumber):返回 Account;如果未找到,则返回 nulltransfer(String fromAccount, String toAccount, double amount):在账户之间转账;如果源账户余额不足,则抛出InsufficientFundsException。成功时,返回"Transferred $[amount] from [fromAccount] to [toAccount]"getTotalDeposits():返回所有账户余额的总和
Main.java:构建你的银行系统!你会收到一个以逗号分隔的命令字符串:SAVINGS:accountNumber:balance:interestRateCHECKING:accountNumber:balance:overdraftLimitDEPOSIT:accountNumber:amountWITHDRAW:accountNumber:amountTRANSFER:fromAccount:toAccount:amountINTEREST:accountNumber
处理每条命令并打印:
- SAVINGS/CHECKING:
Account created: [accountNumber] - DEPOSIT:
Deposited $[amount] to [accountNumber] - WITHDRAW:成功时打印
Withdrew $[amount] from [accountNumber],否则打印Withdrawal failed: [accountNumber] - TRANSFER:打印成功消息,或打印
Transfer failed: [exception message] - INTEREST:
Interest applied to [accountNumber]
处理完所有命令后,打印
--- Bank Summary ---,然后打印每个账户的详情(使用getDetails()),最后打印Total deposits: $[total],并将总额格式化为 2 位小数。
你会收到一个输入:以逗号分隔的命令字符串。
例如,输入为 SAVINGS:SAV001:1000.00:0.05,CHECKING:CHK001:500.00:200.00,DEPOSIT:SAV001:250.00,WITHDRAW:CHK001:600.00,TRANSFER:SAV001:CHK001:100.00,INTEREST:SAV001 时,输出将为:
Account created: SAV001
Account created: CHK001
Deposited $250.00 to SAV001
Withdrew $600.00 from CHK001
Transferred $100.00 from SAV001 to CHK001
Interest applied to SAV001
--- Bank Summary ---
SAV001 (Savings): $1207.50
CHK001 (Checking): $0.00
Total deposits: $1207.50注意,尽管支票账户的余额只有 $500,它仍允许取出 $600:这就是透支保护的作用!储蓄账户会在转账后按余额赚取 5% 的利息。这个挑战将继承、接口、多态、自定义异常和封装结合起来,构建出一个真实的银行应用!
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: 创建一个 Bank 实例
// TODO: 按逗号拆分 input,得到各条命令
// TODO: 处理每条命令:
// - SAVINGS:accountNumber:balance:interestRate -> 创建 SavingsAccount,打印 "Account created: [accountNumber]"
// - CHECKING:accountNumber:balance:overdraftLimit -> 创建 CheckingAccount,打印 "Account created: [accountNumber]"
// - DEPOSIT:accountNumber:amount -> 存款并打印 "Deposited $[amount] to [accountNumber]"
// - WITHDRAW:accountNumber:amount -> 取款,并打印成功信息或 "Withdrawal failed: [accountNumber]"
// - TRANSFER:fromAccount:toAccount:amount -> 转账,并打印成功信息或 "Transfer failed: [exception message]"
// - INTEREST:accountNumber -> 计算利息并打印 "Interest applied to [accountNumber]"
// TODO: 处理完所有命令后,打印 "--- Bank Summary ---"
// TODO: 使用 getDetails() 打印每个账户的详细信息
// TODO: 将 "Total deposits: $[total]" 格式化为保留 2 位小数后打印
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器