ATM自动取款机模拟系统是Java面向对象入门阶段非常经典的练习项目,通过实现账户查询、存款、取款、转账等核心功能,可以很好地理解封装、类与对象的设计逻辑。下面我们一步步完成这个系统的开发。

需求梳理
我们需要实现的核心功能包括:账户登录、余额查询、存款、取款、转账、修改密码、退出系统。每个账户包含卡号、密码、姓名、余额四个属性,这些属性需要通过封装保护,不能直接被外部修改。
封装设计思路
整个系统分为三个核心类:
- Account类:封装账户属性,提供属性的访问和修改方法,保证属性安全
- ATM类:封装ATM的操作逻辑,包括登录验证、各类业务处理
- ATMDemo类:主程序类,负责启动系统和处理用户交互
代码实现
1. 账户类Account
账户类将卡号、密码、姓名、余额设为私有属性,通过getter和setter方法控制访问,比如余额不能直接修改,只能通过存款取款方法调整。
public class Account {
// 私有属性,外部无法直接访问
private String cardId;
private String password;
private String name;
private double balance;
// 构造方法,初始化账户信息
public Account(String cardId, String password, String name, double balance) {
this.cardId = cardId;
this.password = password;
this.name = name;
this.balance = balance;
}
// getter方法,提供属性访问
public String getCardId() {
return cardId;
}
public String getPassword() {
return password;
}
public String getName() {
return name;
}
public double getBalance() {
return balance;
}
// 修改密码方法,验证旧密码后修改
public boolean updatePassword(String oldPwd, String newPwd) {
if (this.password.equals(oldPwd)) {
this.password = newPwd;
return true;
}
return false;
}
// 存款方法
public void deposit(double amount) {
if (amount > 0) {
this.balance += amount;
}
}
// 取款方法,验证余额是否充足
public boolean withdraw(double amount) {
if (amount > 0 && amount <= this.balance) {
this.balance -= amount;
return true;
}
return false;
}
}
2. ATM操作类
ATM类维护账户集合,实现登录验证和各类业务操作,所有操作都通过调用Account类的方法完成,不直接修改账户属性。
import java.util.ArrayList;
import java.util.Scanner;
public class ATM {
private ArrayList<Account> accounts = new ArrayList<>();
private Scanner sc = new Scanner(System.in);
private Account currentAccount; // 当前登录的账户
// 初始化测试账户
public void initAccounts() {
accounts.add(new Account("1001", "123456", "张三", 5000));
accounts.add(new Account("1002", "654321", "李四", 3000));
}
// 启动ATM系统
public void start() {
initAccounts();
while (true) {
System.out.println("===== ATM自动取款机 =====");
System.out.println("1. 登录");
System.out.println("2. 退出");
System.out.print("请选择操作:");
int choice = sc.nextInt();
if (choice == 1) {
login();
} else if (choice == 2) {
System.out.println("感谢使用,再见");
break;
} else {
System.out.println("输入无效,请重新选择");
}
}
}
// 登录验证
private void login() {
System.out.print("请输入卡号:");
String cardId = sc.next();
System.out.print("请输入密码:");
String password = sc.next();
for (Account acc : accounts) {
if (acc.getCardId().equals(cardId) && acc.getPassword().equals(password)) {
currentAccount = acc;
System.out.println("登录成功,欢迎您 " + acc.getName());
showMenu();
return;
}
}
System.out.println("卡号或密码错误,登录失败");
}
// 登录后的功能菜单
private void showMenu() {
while (currentAccount != null) {
System.out.println("n===== 业务菜单 =====");
System.out.println("1. 余额查询");
System.out.println("2. 存款");
System.out.println("3. 取款");
System.out.println("4. 转账");
System.out.println("5. 修改密码");
System.out.println("6. 退出登录");
System.out.print("请选择操作:");
int choice = sc.nextInt();
switch (choice) {
case 1:
queryBalance();
break;
case 2:
deposit();
break;
case 3:
withdraw();
break;
case 4:
transfer();
break;
case 5:
updatePassword();
break;
case 6:
currentAccount = null;
System.out.println("已退出登录");
break;
default:
System.out.println("输入无效,请重新选择");
}
}
}
// 余额查询
private void queryBalance() {
System.out.println("当前账户余额:" + currentAccount.getBalance() + " 元");
}
// 存款操作
private void deposit() {
System.out.print("请输入存款金额:");
double amount = sc.nextDouble();
if (amount > 0) {
currentAccount.deposit(amount);
System.out.println("存款成功,当前余额:" + currentAccount.getBalance() + " 元");
} else {
System.out.println("存款金额必须大于0");
}
}
// 取款操作
private void withdraw() {
System.out.print("请输入取款金额:");
double amount = sc.nextDouble();
if (currentAccount.withdraw(amount)) {
System.out.println("取款成功,当前余额:" + currentAccount.getBalance() + " 元");
} else {
System.out.println("取款失败,余额不足或金额无效");
}
}
// 转账操作
private void transfer() {
System.out.print("请输入对方卡号:");
String targetCardId = sc.next();
Account targetAcc = null;
for (Account acc : accounts) {
if (acc.getCardId().equals(targetCardId) && acc != currentAccount) {
targetAcc = acc;
break;
}
}
if (targetAcc == null) {
System.out.println("对方卡号不存在或不能给自己转账");
return;
}
System.out.print("请输入转账金额:");
double amount = sc.nextDouble();
if (currentAccount.withdraw(amount)) {
targetAcc.deposit(amount);
System.out.println("转账成功,当前余额:" + currentAccount.getBalance() + " 元");
} else {
System.out.println("转账失败,余额不足或金额无效");
}
}
// 修改密码
private void updatePassword() {
System.out.print("请输入旧密码:");
String oldPwd = sc.next();
System.out.print("请输入新密码:");
String newPwd = sc.next();
if (currentAccount.updatePassword(oldPwd, newPwd)) {
System.out.println("密码修改成功,请重新登录");
currentAccount = null;
} else {
System.out.println("旧密码错误,修改失败");
}
}
}
3. 主程序类
主程序只需要创建ATM对象并启动即可,不需要处理具体业务逻辑,符合单一职责原则。
public class ATMDemo {
public static void main(String[] args) {
ATM atm = new ATM();
atm.start();
}
}
封装特性体现
在这个系统中,Account类的balance属性是私有的,外部无法直接修改余额,只能通过deposit和withdraw方法调整,这就是封装的核心作用:隐藏内部实现细节,只暴露安全的操作接口,避免外部错误修改导致数据异常。同时ATM类的账户集合和操作逻辑也被封装在内部,主程序只需要调用start方法即可,不需要关心内部实现。
扩展建议
完成基础功能后,可以尝试扩展更多功能,比如添加开户功能、交易记录查询、每日取款限额限制等,进一步练习面向对象的继承、多态特性,提升代码设计能力。