Java实现ATM机模拟系统(Week2)

目录

前言

项目规划(第二周)

具体实现

用户大类

AccountOperations接口

UserOperations接口

Operations类(实现类)

Account类

User类

Area类 (父类)

货币大类 

Money类(抽象类)

操作界面

LoginInterface类

MainInterface类

RegistrationInterface类

三个界面的txt文档设计

后言


前言

上一周对ATM机模拟系统做了项目需求分析(Java实现ATM机模拟系统(week1)-CSDN博客),这周来做部分的实现。

项目规划(第二周)

  • 完成操作页面展示

  • 完成用户的登录。注册等用户基本操作

  • 学习I/O,要求用户数据必须持久化(也可使用jdbc+mysql)

  • 做好类的封装,自定义异常处理

具体实现

用户大类

AccountOperations接口

该接口主要定义了对帐户进行的操作方法,包括以下

  • 创建账户
  • 登录账户
  • 退出账户
  • 保存账户信息
  • 调出账户信息
package Account.Operations.Method;

import Account.Account;
import Area.Area;

import java.io.FileNotFoundException;

public interface AccountOperations {
    public Account createAccount( Area area); // 创建账户
    public Account landAccount( String accountNumber, String cipher); // 登录账户
    public void logOut( Account account) throws FileNotFoundException;  // 退出账户
    public void saveAccountInformation( Account account);
    public Account retrieveAccountInformation( String accountNumber, String cipher);
}

UserOperations接口

该接口主要定义了用户执行的操作方法,目前包括以下

  • 存款
  • 取款
  • 查询余额
  • 修改密码
package Account.Operations.Method;

import Account.Account;
import Currency.Money;

public interface UserOperations {
    public void saveMoney( Money money, Account account); // 存钱
    public void withdraw( Money money, Account account); // 取钱
    public boolean checkBalance(Account account); // 查询余额
    public void changeCipher( Account account); // 修改密码
}

Operations类(实现类)

该类用于实现以上两个接口的方法

package Account.Operations;

import Account.Account;
import Account.Operations.Method.AccountOperations;
import Account.Operations.Method.UserOperations;
import Area.Area;
import Currency.Money;
import OperationInterface.LoginInterface;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.SecureRandom;
import java.util.Scanner;

public class Operations implements AccountOperations, UserOperations {
    Operations operations = new Operations();
    LoginInterface loginInterface = new LoginInterface();


    @Override
    public Account createAccount( Area area) {
        Scanner s = new Scanner(System.in);

        // 给出账号
        System.out.println("输入本人身份证号码:");
        String id = s.next();
        // 给出手机号
        System.out.println("输入本人手机号:");
        String mobileNumber = s.next();
        StringBuilder ac = new StringBuilder();
        ac.append(area.obtainNumber());
        SecureRandom num = new SecureRandom();
        for( int i = 0; i < 11; i++) {
            int t = num.nextInt(10);
            ac.append(t);
        }
        String accountNumber = ac.toString();

        // 输入密码
        String cipher =s.next();

        // 创建一个账号,并且初始化账号, 并且返回一个账号
        return new Account( accountNumber, cipher, 0.0, 0.0, 0, id, mobileNumber);
    }

    @Override
    public Account landAccount( String accountNumber, String cipher) {
        // 直接调用retrieveAccountInformation()方法调出相应账户
        Account account = retrieveAccountInformation( accountNumber, cipher);
        if( account == null ) {
            System.out.println("输入账号密码有误,请重新输入!!!");

            // 返回登录操作继续输入账号和密码
            Scanner s = new Scanner(System.in);

            // 如果有什么其他操作, 如 创建账号、修改密码操作, 加这里
            /* ········· */

            // 利用递归函数重复输入,直到能匹配到账号为止
            account = landAccount( s.next(), s.next());
        }
        return account;
    }

    @Override
    public void logOut( Account account) throws FileNotFoundException {
        // 将目前的账号清空, 重复利用
        account = null;
        System.out.println("账号退出成功!!!");

        // 退出账号后的后续操作写这里
        /*  ······   */

        //返回登录界面
        loginInterface.loginInterface();
        //operations.landAccount() ; //


    }
    @Override
    public void saveAccountInformation( Account account) {
        // 为这个账户创建一个文本文档,存放账户信息
        String address = "E:\\Account\\" + account.getAccountNumber() + ".txt";
        File save = new File(address);

        // 如果文件已经存在,直接覆盖掉之前的信息保存
        if( save.exists() ) {
            try (FileOutputStream fileOut = new FileOutputStream(address) ) {
                ObjectOutputStream oos = new ObjectOutputStream(fileOut);
                oos.writeObject(account);
                oos.close();
                fileOut.close();

                System.out.println("账户信息保存成功");
            } catch (IOException e) {
                throw new RuntimeException("账户信息保存失败");
            }
        }

        // 如果文件不存在,者创建一个新文件存放账户信息
        else {
            try {
                if( save.createNewFile() ) {
                    try (FileOutputStream fileOut = new FileOutputStream(address) ) {
                        ObjectOutputStream oos = new ObjectOutputStream(fileOut);
                        oos.writeObject(account);
                        oos.close();
                        fileOut.close();

                        System.out.println("账户信息保存成功");
                    } catch (IOException e) {
                        throw new RuntimeException("账户信息保存失败");
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    @Override
    public Account retrieveAccountInformation( String accountNumber, String cipher) {
        String address = "E:\\Account";
        // 读取指定路径目录
        File dictionary = new File(address);

        // 将该目录中的文件读入到list中
        File[] list = dictionary.listFiles();
        Account result = null;
        if( list != null ) {

            // 通过循环遍历目录中的文件,进行逐个查找
            for( File t : list) {
                Path find = Path.of(t.getAbsolutePath());
                String content = null;
                try {
                    content = new String(Files.readAllBytes(find));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if( content.contains(accountNumber) && content.contains(cipher) ) {
                    // 将目标文件信息读取到一个Account对象中
                    try (FileInputStream in = new FileInputStream(address + "\\" + t.getName())) {
                        ObjectInputStream oos = new ObjectInputStream(in);
                        try {
                            result = (Account) oos.readObject();
                        } catch (ClassNotFoundException e) {
                            throw new ClassCastException("读取用户信息失败!!!");
                        }
                        in.close();
                        oos.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    break;
                }
            }
        }
        else {
            System.out.println("目录为空!!!");
        }
        return result;
    }

    @Override
    public void saveMoney(Money money, Account account) {
        Scanner s = new Scanner(System.in);
        System.out.println("放入所存金额:");
        account.setDeposit(account.getDeposit() + money.MoneyExchange( money, s.nextInt()));

        // 这里也可以采用一个 try - catch 块处理 saveAccountInformation方法中遇到的异常,目前未采用
        saveAccountInformation(account);
        System.out.println("存储成功!!!");
    }

    @Override
    public void withdraw(Money money, Account account) {
        Scanner s = new Scanner(System.in);
        System.out.println("输入要取出金额:");
        int draw = s.nextInt();
        if( draw > account.getDeposit() ) {
            System.out.println("余额不足!!!");
        }
        else {
            // 账户中的货币都是以人民币形式存储的,所以要把取出(存入)的货币转化成人民币
            account.setDeposit(account.getDeposit() - money.MoneyExchange( money, s.nextInt()));
        }
    }

    @Override
    public void changeCipher(Account account) {
        Scanner s = new Scanner(System.in);
        System.out.println("请输入本用户身份证号:");
        String id = s.next();
        System.out.println("请输入本用户手机号:");
        String mobileNumber = s.next();
        String address = "E:\\Account";
        File file = new File(address);
        File[] list = file.listFiles();
        if( list != null ) {
            // 通过循环遍历目录中的文件,进行逐个查找
            for( File t : list) {
                Path find = Path.of(t.getAbsolutePath());
                String content = null;
                try {
                    content = new String(Files.readAllBytes(find));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if( content.contains(id) && content.contains(mobileNumber) ) {
                    // 将目标文件信息读取到一个Account对象中
                    try (FileInputStream in = new FileInputStream(address + "\\" + t.getName())) {
                        ObjectInputStream oos = new ObjectInputStream(in);
                        try {
                            Account result = (Account) oos.readObject();
                            System.out.println("请输入新密码(由六位数组成):");
                            result.setCipher(s.next());
                            System.out.println("密码更改成功!!!");
                            // 保存信息
                            saveAccountInformation(result);
                        } catch (ClassNotFoundException e) {
                            throw new ClassCastException("更改密码时读取用户信息失败!!!");
                        }
                        in.close();
                        oos.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    break;
                }
            }
        }
        else {
            System.out.println("目录为空!!!");
        }
    }

    public boolean checkBalance(Account account) {
        Account result = retrieveAccountInformation( account.getAccountNumber(), account.getCipher());
        if ( result != null ) {
            System.out.println("账户余额为:" + result.getDeposit() + "RMB");
            return true;
        }
        else {
            System.out.println("账户余额查询失败,请重新输入账号和密码!!!");
            return false;
            // 如果查询失败可根据用户选择进行继续查询,这里通过返回值判断是否查询成功
        }
    }
}

Account类

该类是对账户的定义,包括了账户应当具有的属性

包括但不限于

  • 账号
  • 密码
  • 手机号
  • 余额
  • 年利率(待商榷)
  • 时间(待商榷)
  • 用户id
package Account;

import java.io.Serializable;

// 因为要实现账户保存,所以要接Serializable接口
public class Account implements Serializable {
    private String accountNumber;
    private String cipher;
    private Double deposit;
    private Double annualInterestRate;
    private int time;
    private final String id;
    private final String mobileNumber;
    public Account(String accountNumber, String cipher, Double deposit, Double annualInterestRate, int time, String id, String mobileNumber) {
        this.accountNumber = accountNumber;
        this.cipher = cipher;
        this.deposit = deposit;
        this.annualInterestRate = annualInterestRate;
        this.time = time;
        this.id = id;
        this.mobileNumber = mobileNumber;
    }
    @Override
    public String toString() {
        return "Account{" +
                "accountNumber='" + accountNumber + '\'' +
                ", cipher='" + cipher + '\'' +
                ", deposit=" + deposit +
                ", annualInterestRate=" + annualInterestRate +
                ", time=" + time +
                '}';
    }
    private int getTime() {
        return time;
    }
    public String getAccountNumber() {
        return accountNumber;
    }
    public String getCipher() {
        return cipher;
    }
    public Double getAnnualInterestRate() {
        return annualInterestRate;
    }
    public Double getDeposit() {
        return deposit;
    }
    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }
    public void setDeposit(Double deposit) {
        this.deposit = deposit;
    }
    public void setAnnualInterestRate(Double annualInterestRate) {
        this.annualInterestRate = annualInterestRate;
    }
    public void setTime(int time) {
        this.time = time;
    }
    public void setCipher(String cipher) {
        this.cipher = cipher;
    }
    public String getId() {
        return id;
    }
    public String getMobileNumber() {
        return mobileNumber;
    }
}

User类

该类是面向用户的,主要实现了用户使用系统时的操作逻辑,通过用户输入的操作数来执行对应的操作。

package User;

import Account.Account;
import Account.Operations.Operations;
import OperationInterface.LoginInterface;
import OperationInterface.MainInterface;
import OperationInterface.RegistrationInterface;

import java.io.FileNotFoundException;
import java.util.Scanner;

import static java.lang.System.exit;

public class User {
    public void userOperation() throws FileNotFoundException {
        // 跳出首页画面提示用户
        /* ······· */

        Scanner s = new Scanner(System.in);
        Account account = null;
        Operations operation = new Operations();
        System.out.println("输入 1 登录账户   输入 2 创建新账户  ");
        int userOperation = s.nextInt();

        if(userOperation == 1){
            LoginInterface loginInterface = new LoginInterface();
            loginInterface.loginInterface();
            Operations operations = new Operations();

            //调用登录方法
            //operations.landAccount(); //
            //如何判断登录成功?成功则进入主界面

            MainInterface mainInterface = new MainInterface();
            mainInterface.mainInterface(); //展示主界面
        }else if (userOperation == 2){
            RegistrationInterface registrationInterface = new RegistrationInterface();
            registrationInterface.registrationInterface();
            Operations operations = new Operations();

            //调用创建账户方法
            //operations.createAccount(); 
        }else {
            System.out.println("您进行的操作不合法!");
        }

        // 以下可以根据页面直接加操作
        /* ············· */
    }

    public void mainInterfaceOperation(){//主界面操作
        Scanner scanner = new  Scanner(System.in) ;
        Operations operations = new Operations();
        int n = scanner.nextInt();

        if (n == 1){//调用存款方法
            //operations.saveMoney(); //
        }else if(n == 2){//调用取款方法
           //operations.withdraw(); //
        }else if(n == 3){//调用查询余额方法
            //operations.checkBalance() ;///
        }else if(n == 4){//调用货币交换方法 !!未实现

        }else if(n == 5){//调用修改密码方法
            //operations.changeCipher(); 
        }else if(n == 6){//调用操作日志查询方法 !!未实现

        }else if(n == 7){//调用退出账户方法,返回登录界面
           //operations.logOut(); ///
        }else if(n == 8){//退出系统,即终止程序运行
            exit(0) ;
        }
    }
}

Area类 (父类)

在创建账户时,需要根据用户所在地区给出前几位数字,我们用一个Area父类来实现这一功能,每个不同的地区均是其子类

package Area;

public class Area {
    public String name;

    public Area(String name) {
        this.name = name;
    }

    public String obtainNumber() {
        return null;
    }
}

货币大类 

本周货币大类不在需要实现的范围内,故只进行了简单的架构

Money类(抽象类)

主要实现货币交换的方法,每个不同的币种均是其子类

package Currency;

public abstract class Money {
    public Double exchangeRate; // 汇率, 人民币与该货币的比
    public abstract Double MoneyExchange( Money money, int num); // 某货币交换成人民币
    public abstract  Double ExchangeMoney( Money money, int num);// 人民币交换成某货币
}

操作界面

目前实现了三个界面

  • 登录界面
  • 注册界面
  • 主界面

界面的实现极其简单,无非是几个文件创建和输出的事情罢了。

LoginInterface类

package OperationInterface;

import java.io.*;

public class LoginInterface {
    public void loginInterface() throws FileNotFoundException {
        File file = new File("Login.txt"); //创建File类对象,并给出其相对路径,否则默认创建在当前路径下

        if (file.exists()) { //调用exists方法,判断文件是否存在
            fileInput(file); //如已存在,直接打开
        } else { //如不存在,执行创建操作
            try {
                file.createNewFile();
                fileInput(file);
            } catch (Exception e) {
                System.out.println("系统故障!");
            }
        }

    }

    private void fileInput(File file) {
        FileReader f = null;//文件读取对象
        BufferedReader f1 = null;//字符流对象
        try {
            f = new FileReader(file);
            f1 = new BufferedReader(f);
            //循环打印cc文件中的每行数据
            String str = null;
            while ((str = f1.readLine()) != null) {
                System.out.println(str);
            }

        } catch (Exception e) {
            System.out.println("系统故障!");
        } finally {
            try {
                f1.close();
                f.close();
            } catch (Exception e2) {
                System.out.println("系统故障!");
            }
        }
    }
}

MainInterface类

package OperationInterface;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class MainInterface {
    public void mainInterface() throws FileNotFoundException {
        File file = new File("Main.txt"); //创建File类对象,并给出其相对路径,否则默认创建在当前路径下

        if (file.exists()) { //调用exists方法,判断文件是否存在
            fileInput(file); //如已存在,直接打开
        } else { //如不存在,执行创建操作
            try {
                file.createNewFile();
                fileInput(file);
            } catch (Exception e) {
                System.out.println("系统故障!");
            }
        }

    }

    private void fileInput(File file) {
        FileReader f = null;//文件读取对象
        BufferedReader f1 = null;//字符流对象
        try {
            f = new FileReader(file);
            f1 = new BufferedReader(f);
            //循环打印cc文件中的每行数据
            String str = null;
            while ((str = f1.readLine()) != null) {
                System.out.println(str);
            }

        } catch (Exception e) {
            System.out.println("系统故障!");
        } finally {
            try {
                f1.close();
                f.close();
            } catch (Exception e2) {
                System.out.println("系统故障!");
            }
        }
    }
}

RegistrationInterface类

package OperationInterface;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class RegistrationInterface {
    public void registrationInterface() throws FileNotFoundException {
        File file = new File("Registration.txt"); //创建File类对象,并给出其相对路径,否则默认创建在当前路径下

        if (file.exists()) { //调用exists方法,判断文件是否存在
            fileInput(file); //如已存在,直接打开
        } else { //如不存在,执行创建操作
            try {
                file.createNewFile();
                fileInput(file);
            } catch (Exception e) {
                System.out.println("系统故障!");
            }
        }

    }

    private void fileInput(File file) {
        FileReader f = null;//文件读取对象
        BufferedReader f1 = null;//字符流对象
        try {
            f = new FileReader(file);
            f1 = new BufferedReader(f);
            //循环打印cc文件中的每行数据
            String str = null;
            while ((str = f1.readLine()) != null) {
                System.out.println(str);
            }

        } catch (Exception e) {
            System.out.println("系统故障!");
        } finally {
            try {
                f1.close();
                f.close();
            } catch (Exception e2) {
                System.out.println("系统故障!");
            }
        }
    }
}

三个界面的txt文档设计

//登录界面               
               登录

账号:
密码:



//注册界面
               注册

请输入身份证号:
请输入手机号:
请输入密码:



//主界面
               欢迎

1.存款            2.取款
3.查询余额         4.货币交换
5.更改密码         6.操作日志查询
7.退出账户         8.退出系统

后言

本周主要实现了用户的部分基本操作,采用的主要手段为文件操作(文件的写入与读取也有博客记录Java文件操作(从创建文件到简单输入输出流)-CSDN博客),用于存储数据,设计操作界面等。在和朋友进行合作开发的过程中,我们也遇到了许多问题,比如当我们分析完项目需求后,双方就开始着手写代码实现,却没有提前沟通好代码逻辑,导致虽然写了注释,互相读代码时也遇到了不小的障碍(所以大家千万别学我们

新手上路,水平有限,如有错误,还望海涵并指出!

与君共勉!

  • 19
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eternal*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值