注:本节教材内容,与上期推送的《核心试验:重构WoniuATM并完善其功能(一)》为一个章节。
回顾上节内容,请点击:核心实验:重构WoniuATM并完善其功能(一)
实验流程
5.实现UserData数据类:
package com.woniuxy.atm.two;
public class UserData { private String username;// 用户名 private String password;// 密码 private String phone;// 手机号码 private double balance;// 账户余额 private boolean isAdmin;// 是否管理员(用于初始用户设定) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public boolean isAdmin() { return isAdmin; } public void setAdmin(boolean isAdmin) { this.isAdmin = isAdmin; } // 默认构造方法,由于有两个构造方法,所以必须显式声明 public UserData() {}
// 构造方法,快速设置初始用户或完成注册。也可用setter和getter挨个属性设置,均可 public UserData(String username, String password, String phone, int balance, boolean isAdmin) { this.username = username; this.password = password; this.phone = phone; this.balance = balance; this.isAdmin = isAdmin; } } |
6.实现UserManager类:
到目前为止代码框架已经为大家搭建完毕,接下来,就需要读者来独立完成更多的代码实现了。
对于用户管理类的实现,我们着重先来梳理一下思路,并演示注册代码的实现,登录的验证就交给读者朋友自行实现了。
(1).首先,我们已经学习了数组和List对象,我们认为使用List对象来管理用户会更加方便。
(2).其次,List对象里面应该存放什么数据类型?字符串?显然不是,应该存在UserData数据类的多个实例,每个实例对应一个用户。所以我们应该使用List<UserData>类型来定义该列表对象。
(3).再者,该List对象会在注册,登录甚至转账,存款中都会用到,所以我们应该将其定义为类级成员变量,而不应该是某个方法的局部变量。
(4).最后,由于我们经验会实例化UserManager类,所以为了保证实例化过程中不清空已经注册的用户,我们应该将该类级成员变量定义为:static静态,这样可以不随实例化过程而消失。
(5).所以,最终,我们在UserManager的类级定义了一个静态成员变量,代码如下:
static List<UserData> uds = new ArrayList<UserData>(); |
有了这个基础前提后,我们先通过重写UserManager的构造方法来完成初始用户的设置:
// 利用构造方法来完成两个默认用户的初始化设置,方便代码的调试,不用每次都要先注册 public UserManager() { UserData ud1 = new UserData(); ud1.setUsername("admin"); ud1.setPassword("adminpass"); ud1.setBalance(5000); ud1.setPhone("13812345678"); ud1.setAdmin(true); uds.add(ud1); // 将第一个默认用户添加到uds列表对象中 UserData ud2 = new UserData("woniu","woniupass","18081089811",5000,false); uds.add(ud2); // 利用UserData的重载构造方法快速完成初始用户创建 } |
接下来,我们来实现register方法,最后的UserManager的完整代码实现(除login()方法外)如下:
package com.woniuxy.atm.two;
import java.util.ArrayList; import java.util.List; import java.util.Scanner;
public class UserManager { // 将uds定义为类级静态成员变量,可以确保不会在实例化时将注册的数据清空 // 使用List列表来处理用户信息,相当于uds对象中可以保存多个UserData实例 static List<UserData> uds = new ArrayList<UserData>(); // 定义静态变量loggedUserIndex,用于保存登录用户在uds中的下标,便于后续使用 public static int loggedUserIndex = -1;
// 利用构造方法来完成两个默认用户的初始化设置,方便代码的调试,不用每次都要先注册 public UserManager() { UserData ud1 = new UserData(); ud1.setUsername("admin"); ud1.setPassword("adminpass"); ud1.setBalance(5000); ud1.setPhone("13812345678"); ud1.setAdmin(true); uds.add(ud1); // 将第一个默认用户添加到uds列表对象中 UserData ud2 = new UserData("woniuxy","123456","18081089811",5000,false); uds.add(ud2); // 利用UserData的重载构造方法快速完成初始用户创建 } // 实现登录功能 public void login() { Scanner sc = new Scanner(System.in); System.out.println("请输入用户名:"); String username = sc.next(); System.out.println("请输入密码:"); String password = sc.next(); int userIndex = this.checkUserExist(username); if (userIndex != -1) { // 利用userIndex去查找List对象uds,用以对比其密码 if (password.equals(uds.get(userIndex).getPassword())) { System.out.println("恭喜你,登录成功。"); // 将登录成功后的用户下标保存在静态变量loggedUserIndex中 UserManager.loggedUserIndex = userIndex; new MainUI().subMenu(); } else { System.out.println("抱歉,你的密码错误,请重新登录。"); this.login(); } } else { System.out.println("抱歉,你的用户名错误,请重新输入。"); this.login(); } } // 实现注册功能 public void register() { Scanner sc = new Scanner(System.in); System.out.println("请输入你的用户名:"); String username = sc.next(); // 如果用户名已经存在,则提示用户重新输入 if (this.checkUserExist(username) >= 0) { System.out.println("你注册的用户名已经存在,请重新输入."); this.register(); } else { System.out.println("请输入你的密码:"); String password = sc.next(); System.out.println("请输入你的电话号码:"); String phone = sc.next(); UserData ud = new UserData(); ud.setUsername(username); ud.setPassword(password); ud.setPhone(phone); ud.setAdmin(false); ud.setBalance(5000); uds.add(ud); System.out.println("恭喜,注册成功,现在跳转到主菜单."); new MainUI().mainMenu(); } } // 为登录和注册提供一个通用的辅助方法,检查用户名是否存在 // 如果用户名存在,则返回对应的用户名所在的列表对象中的下标,否则返回-1 private int checkUserExist(String username) { int index = -1; for (int i=0; i<uds.size(); i++) { if (username.equals(uds.get(i).getUsername())) { index = i; break; } } return index; } } |
上述代码的运行效果如下图所示:
7.实现AccountManager类:
其实AccountManager类的四大功能实现,需要特别注意以下几点:
(1).我们需要通过登录的过程,记录下当前登录成功的用户名或用户下标,进而对该用户进行查询,存取款操作。前述代码已经利用静态成员变量loggedUserIndex保存了登录用户在uds中的下标。
(2).可以利用当前登录用户的下标,进而查询uds对象中的对应该用户名的余额。
(3).存取款操作则是直接对当前登录的用户进行余额的增加和减少即可。
(4).关于转账的功能,我们需要明确对方账户是否真实存在,所以这个校验是必不可少的。
下面我们就来看看转账功能的代码是如何实现的,其它功能请读者自行实现:
public void transfer() { Scanner sc = new Scanner(System.in);
// 根据loggedUserIndex的下标获取到当前的登录用户信息 int fromUserIndex = UserManager.loggedUserIndex; UserData fromAccount = UserManager.uds.get(fromUserIndex);
System.out.println("请输入对方账户:"); String toUsername = sc.next();
// 检查用户输入的账号是否正确,正确的话直接获取到其在uds中的下标 int toUserIndex = new UserManager().checkUserExist(toUsername);
if (toUserIndex != -1) { UserData toAccount = UserManager.uds.get(toUserIndex); System.out.println("请输入转账金额:"); double money = sc.nextDouble(); // 转账金额必须为正数,同时不能大于本人账户的现有余额 if (money > 0 && money <= fromAccount.getBalance()) { // 转账后当前登录的账户余额将减少 double myBalance = fromAccount.getBalance() - money; fromAccount.setBalance(myBalance); // 转账后对方账户余额将增加 double toBalance = toAccount.getBalance() + money; toAccount.setBalance(toBalance); new MainUI().subMenu(); } else { System.out.println("你输入的转账金额不对."); } } else { System.out.println("你输入的对方账户不存在."); this.transfer(); } } |
思考练习
1.为UserManager类添加修改密码和修改电话号码两个新功能。
2.为AccountManager类添加操作流水功能,并记录下来。
3.对上述代码进行测试,完成相应的BUG的修改。
4.思考上述代码还有哪些不足之处,应该如何修改?从测试的角度来看呢?
下周推送:预备知识:Java异常处理机制