java实现简易超市管理系统02(含源码)

java超市管理系统 1.1(含源文件,后续会继续优化~)


前言

继上一篇文章超市管理系统1.0,在增删改查的基础上,本篇中的程序加入了如下功能

  1. 两种用户身份的登录和切换功能
  2. 顾客用户的购买商品功能和支付功能
  3. 所有商品信息可存储到本地硬盘

另外,本篇中的程序在商品的存储结构上也由ArrayList集合改为了TreeMap集合

关于增删改查的需求这里就不过多赘述了~这里只说一下前言中提及的三种新的功能所对应的需求

一. 两种用户身份的登录和切换功能

1 分析两种身份的权限及实现

我们首先先来分析一波:程序分为不同身份的用户的目的,无非就是为了区分顾客超市管理者这两种身份在使用程序时候,所访问的程序功能和数据是不同的
显然,顾客的权限更少一些,面向顾客功能也少一些。

如下图所示:分别表示顾客登录的主菜单和管理员登录的主菜单

可以看到:管理员用户有所有功能和数据的访问权限;顾客用户只有查询、购买的功能和部分数据的访问权限

在这里插入图片描述

还有一点就是,用户在访问数据(例如查看商品信息、查询商品信息)的时候,不应该显示商品的进价。
我们就可以在显示商品信息的部分根据不同用户的身份,调用不同的方法来实现不同数据的显示。

我们该如何区分用户的身份呢?

我们可以定义:管理员用户有且仅有一套用户名和密码,登录成功后标记为true,表示此时是管理员用户正在使用;普通用户(顾客身份)登录后,标记为false,表示此时为顾客正在使用。接着,把这个标记赋给一个变量(例如usersId把这个userId变量在相应的方法中作为参数传递,达到不同身份,不同功能,不同权限的效果。

2 分析登录功能的实现

成功登录的核心满足条件就是:当用户名和密码同时与存储的内容相一致的时候,用户登录成功,否则失败。

因此,我们可以使用带缓冲的字符输入流BufferedReader向内存中读取数据,一次读取一行,再根据中间的等号把字符串分割为用户名和密码,并分别暂存到一个字符串类型的数组中,当用户输入的用户名和密码和查找到的某一条信息相同的时候,系统认定登陆成功,否则登陆失败。

@Override
public boolean isLogin(String userName, String passWord) {
    boolean flag = false;
    try {
        //创建带有缓冲的字符输入流来给文件读取数据
        BufferedReader br = new BufferedReader(new FileReader("O:\\javaSE练习" +
                "\\src\\supermarket_manager_system_1_1_1\\user.txt"));
        String line;
        while ((line = br.readLine()) != null) {
            String[] s = line.split("=");
            if (s[0].equals(userName) && s[1].equals(passWord))
                flag = true;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return flag;
}

3 分析注册功能的实现

注册功能的实现思路为:(向内存中)输入自定义的用户名和密码后,通过IO流来把用户输入的账号和密码存储起来(本程序使用的是带有缓冲的字符输出流BufferedWriter

需要注意的就是传入参数的时候要注意信息的追加(即FileWriter的第二个参数为true)。

@Override
    public void regist(UsersInfo usersInfo) throws IOException {
        try {
            //把用户信息存到文件中
            //用户名和密码用等号隔开
            String info = usersInfo.getUserName() + "=" + usersInfo.getPassWord();
            //创建带有缓冲的字符输出流来给文件写入数据,创建了一个可以追加写入的FileWriter,避免了文件中之前的用户信息被覆盖
            BufferedWriter bw = new BufferedWriter(new FileWriter("O:\\javaSE练习\\src" +
                    "\\supermarket_manager_system_1_1_1\\user.txt", true));
            bw.write(info); //写入信息
            bw.newLine(); //换行
            bw.flush(); //刷新
            bw.close(); //关闭
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4 分析切换用户功能的实现

用户使用这个系统时,如果需要切换身份来查看商品信息,那么只能重新登录,那么我们可以加入一个功能(编写一个方法)使得用户想切换身份的时候,可以跳转到登录界面。

case 3:
      return wares; //当(管理员)用户对商品信息“增删改查完毕后”,从这里返回wares对象以实现刷新!!

只需要在相应的流程控制语句中,达到跳出当前流程并跳转到“登录界面”即可实现切换用户功能

二. 顾客用户的购买商品功能和支付功能【重点】

大体思路为设置相应的方法,通过调用实现功能

但是!在实现购买支付功能前,我们要明确以下几点:

  • 在购买的过程中,如何对用户已经选择的商品进行存储
  • 对于多次购买同一件商品,如何保证用户输入购买的数量合法
  • 如何对用户已经选择的商品清单进行结算
  • 在结算前,用户想要更改购买的数量,这时候如何做到商品的库存和结算金额实现同步
  • 支付完毕后,如何使得商品的库存真正的减少
  • 顾客的“购物车合并”问题

下面让我们一一分析一下~

1.在购买的过程中,如何对用户已经选择的商品进行存储?

我们可以定义一个购物车类BuyCar,这个类中有某种类型的属性,可以用于存储用户已经预购的商品信息

对于存储这些信息(用户购买的商品id购买数量),我们可以用集合中的ArrayListHashMapTreeMap等常用集合来存储。

为了在结算时候便于增删商品信息以及结算时候便于计算总价格,我们采用TreeMap这样键值对的形式进行存储(自动使得购物车中的商品不重复),键为商品编号,值为商品购买数量。

这样购物车类的TreeMap<String, Integer>类型的属性就确立了。

public class BuyCar {
    private TreeMap<String, Integer> waresInBuyCar;

    /**
     *  构造方法
     */
    public BuyCar(TreeMap<String, Integer> waresInBuyCar) {
        this.waresInBuyCar = waresInBuyCar;
    }

    /**
     *  setter/getter
     */
    public TreeMap<String, Integer> getWaresInBuyCar() {
        return waresInBuyCar;
    }

    public void setWaresInBuyCar(TreeMap<String, Integer> waresInBuyCar) {
        this.waresInBuyCar = waresInBuyCar;
    }

}

2. 对于多次购买同一件商品,如何保证用户输入购买的数量合法?

当用户要修改购买数量或者要输入购买数量的时候,对用户的输入和所有商品信息中的库存进行比较,如果超出了库存量,则需要用户重新输入。这样就确保了所有商品的库存量非负,使得程序更加合理。

//当想要购买的数量大于库存或者小于0的时候,加入购物车失败
if (wantCount > allWares.get(tempId).getCount() || wantCount < 0) {
	System.out.println("【提示】当前[" + allWares.get(tempId).getName() + "]的库存量为"
                            + allWares.get(tempId).getCount() + ", 请您重新输入");
} else {
	waresInBuyCar.put(tempId, wantCount); //将商品放入购物车
	 break;
}

3. 如何对用户已经选择的商品清单进行结算?

由于购物车中的属性是TreeMap集合类型的,因此我们可以使用增强for循环来计算共需要支付的钱数。

//开始计算要支付多少钱
for (String wareId : buyCar.getWaresInBuyCar().keySet()) {
    Integer buyingCount = buyCar.getWaresInBuyCar().get(wareId);
    needPay += buyingCount * allWares.get(wareId).getOutPrice();
}

4. 在结算前,用户想要更改购买的数量,这时候如何做到商品的库存和结算金额实现同步?

把修改购物清单的代码放入while循环中,在while循环中不断对buyCar购物车对象进行改变即可。

直到用户确认支付,这时候,就开始更新库存(新库存=旧库存-购买数量),然后while循环结束,购买功能结束

/*
        一定要刷新库存!!!!!!
 */
int oldCount; //购买前的库存(
int wantCount; //想要购买的数量
for (String wareId : buyCar.getWaresInBuyCar().keySet()) {
    oldCount = allWares.get(wareId).getCount();
    wantCount = buyCar.getWaresInBuyCar().get(wareId);
    //新的库存 = 购买前的库存 - 购买的数量)
    allWares.get(wareId).setCount(oldCount - wantCount);
} //刷新完毕!!!

5. 支付完毕后,如何使得商品的库存真正的减少?

一旦用户支付完毕,购买功能结束,购买功能对应的方法中,将所有商品allWares这个TreeMap<String,Wares_Info>类型的变量作为返回值返回,使得整个程序的商品信息都公用一份allWares变量。

return allWares;

6. 顾客的“购物车合并”问题

购买功能中:我们在四类商品的每一个类中加入了可被购买的方法,这个方法的返回值类型是购物车BuyCar类型,也就是说,如果用户选择购买四类商品,我们在每一个购买方法中新建一个存储该类商品的购物车,再把四个购物车整合到一起,形成一个总的购物车对象,再传入支付功能。

我们如何把这四个购物车整合到一起呢?

由于TreeMap中没有提供相应方法。因此我们可以自己写一个方法使得把一个TreeMap1集合加入到另一个TreeMap2集合中,返回TreeMap2集合即可(下面为图解)

在这里插入图片描述

三. 所有商品信息可存储到本地硬盘

1. 字节流?字符流?序列化?应该使用哪个?

我们需要存储的是allWares(所有商品信息对象),对于对象的存储,我们只需要把相应的类实现Serializable接口,然后把对象allWares进行序列化进行存储,反序列化进行读取即可,同样我们可以自己写两个方法分别实现序列化和反序列化。

当程序第一次运行的时候,执行自动初始化所有商品信息的addTestData()方法;当已经存在序列化的文件后,就可以直接读取序列化的文件了(如下图所示)

//通过反序列化读取信息
TreeMap<String, Wares_Info> allWares = null;
try {
    allWares = Tools.readInfo();
} catch (IOException | ClassNotFoundException e) {
    allWares = Tools.addTestData(); //如果用户首次使用,将会自动初始化商品列表,并生成waresInfo文件
}

当用户选择0退出程序的时候,我们需要对allWares对象序列化,以存储用户对商品信息的操作(如下图所示)

case 0:
    Show.showEndMenu();
    /*
    此处应该序列化allWares对象,以实现保存的效果
    */
    Tools.saveInfo(wares);
    System.exit(0);

四. 源码

源码可私信获取~
  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

对方正在长头发_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值