目录
1. 前言
2. 功能实现
3. 功能分析
4. 模块划分
5. UML图
6. 使用技术
7. 代码
三个月前,我就写过这个项目的低级版。之前是利用数组进行商品的存储,所以存在商品数量固定的缺陷。经过三个月的学习,想要对这个项目进行优化,回头看了看当时的代码... 妈耶,写的都是些啥,暂且不说所用的技术比较low,那个框架、思路,简直是一团浆糊。反正我自己是看不下去了,如果你足够有勇气,可以去探个险。想要探险的小伙伴可以点这个链接:https://blog.csdn.net/qq_42142477/article/details/84619958 emmm...我先在这里祝你们好运咯~
痛定思痛,我决定把这个项目再仔细的分析一遍,利用新学到的知识把这个项目优化一下(虽然三个月后的我可能会再次嫌弃这个版本,但是我会以现在的水平,努力把这个项目写的更好。随着之后不断地学习,再慢慢的改进)。
这个版本不只是将框架、思路变得更加清晰,同时还运用了新的知识对一些功能进行了扩充。
编号
旧:利用数组实现,将编号当做数组的索引,编号为int类型
新:用hashMap实现,类型是个泛型,因此可以将编号设置为字符串的形式
订单类
商品信息
由于订单中,商品的编号与数量有所关联,因此,使用map实现商品信息的记录,key为编号,value为数量。
保存功能与加载功能
联系:将数据保存到文件或者数据库,当重新启动时,数据并不在内存中,需要从文件或数据库中加载出来
保存:Java序列化技术(将数据转化为字节流保存至文件)、JDBC技术(insert)、自定义编码技术(XML、JSON)(把数据保存到文件中,每一行保存一个商品对象的属性信息 -> 编码:名称:价格)
加载:Java反序列化技术、JDBC技术、自定义解码技术(从文件中获取数据,编码:名称:价格 -> 商品对象的属性信息)
package com.qqy.newcheck;
/**
* 商品类
* Author:qqy
*/
public class Goods {
private String id;
private String name;
private double price;
public Goods(String id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
@Override
public String toString() {
return String.format("[%2s] %s %.2f",this.getId(),this.getName(),this.getPrice());
}
}
package com.qqy.newcheck;
import java.util.HashMap;
import java.util.Map;
/**
* 订单类
* Author:qqy
*/
public class Order {
//订单创建完成之后,订单编号不能修改
private final String orderId;
//商品信息 -> 商品标号,商品数量
//订单创建完成后,goodsInfo属性实例化HashMap
private final Map goodsInfo = new HashMap<>();
public Order(String orderId) {
this.orderId = orderId;
}
/**
* 添加商品
* @param goodsId 商品编号
* @param count 数量
*/
public void add(String goodsId, Integer count) {
//sum -> 改变后的商品数量
Integer sum = this.goodsInfo.get(goodsId);
//当前订单中不存在该商品
if (sum == null) {
sum = count;
} else {
sum += count;
}
//将新的商品数量与商品编号关联起来
this.goodsInfo.put(goodsId, sum);
}
/**
* 减少商品
* @param goodsId
* @param count
*/
public void cancel(String goodsId, Integer count) {
Integer sum = this.goodsInfo.get(goodsId);
//当前订单存在该商品
if (sum != null) {
sum-=count;
if(sum<=0){
this.goodsInfo.remove(goodsId);
}else{
this.goodsInfo.put(goodsId,sum);
}
}
}
/**
* 清空所有商品
*/
public void clear() {
System.out.println("清空本次订单中的所有信息...");
this.goodsInfo.clear();
}
/**
* 获得订单编号
* @return
*/
public String getOrderId() {
return orderId;
}
/**
* 获得订单信息
* @return
*/
public Map getOrderInfo() {
return this.goodsInfo;
}
}
package com.qqy.newcheck;
/**
* 商品管理
* Author:qqy
*/
public interface GoodsCenter {
/**
* 添加商品
* @param good 商品
*/
void addGoods(Goods good);
/**
* 删除商品(通过商品编号)
* @param goodId
*/
void removeGoods(String goodId);
/**
* 更新商品(修改当前商品编号对应商品的名称)
* @param good
*/
void updateGoods(Goods good);
/**
* 商品是否存在(通过商品编号)
* @param goodId
* @return
*/
boolean isExistGoods(String goodId);
/**
* 获取商品(通过商品编号)
* @param goodId
* @return
*/
Goods getGoods(String goodId);
/**
* 列出商品信息
* @return
*/
String listGoods();
/**
* 存储商品信息
*/
void store();
/**
* 加载商品信息
*/
void load();
}
package com.qqy.newcheck;
/**
* 订单管理
* Author:qqy
*/
public interface OrderCenter {
/**
* 添加订单
* @param order 订单
*/
void addOrder(Order order);
/**
* 删除订单
* @param orderId
*/
void removeOrder(String orderId);
/**
* 列出所有订单信息
* @return
*/
String ordersTable();
/**
* 列出当前订单信息(通过订单编号)
* @param orderId
* @return
*/
String orderTable(String orderId);
/**
* 存储订单信息
*/
void storeOrders();
/**
* 加载订单信息
*/
String loadOrders();
/**
* 清空所有订单信息
*/
void cleanOrders();
}
package com.qqy.newcheck.impl;
import com.qqy.newcheck.GoodsCenter;
import com.qqy.newcheck.Goods;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
/**
* Author:qqy
*/
public class GoodsCenterImpl implements GoodsCenter {
//创建商品集合,key -> 商品编号,value -> 商品名称
private final Map goodsMap = new HashMap<>();
//将商品信息保存至goods.txt
private String filePath = System.getProperty("user.dir") + File.separator + "goods.txt";
@Override
public void addGoods(Goods good) {
this.goodsMap.put(good.getId(), good);
}
@Override
public void removeGoods(String goodId) {
this.goodsMap.remove(goodId);
}
//修改存在商品的名称
@Override
public void updateGoods(Goods good) {
if (this.goodsMap.containsKey(good.getId())) {
this.goodsMap.put(good.getId(), good);
}
}
@Override
public boolean isExistGoods(String goodId) {
return this.goodsMap.containsKey(goodId);
}
@Override
public Goods getGoods(String goodId) {
return this.goodsMap.get(goodId);
}
@Override
public String listGoods() {
StringBuilder str = new StringBuilder();
str.append("************** 商品信息 **************\n");
str.append("\t编号\t\t\t名称\t\t\t单价\n");
//根据商品名称获取商品信息
for (Goods good : this.goodsMap.values()) {
str.append("\t" + good.getId() + "\t\t\t" + good.getName() + "\t\t\t" + good.getPrice() + "\n");
}
str.append("*************************************\n");
return str.toString();
}
@Override
public void store() {
System.out.println("保存所有商品信息到文件,每个商品信息 -> 编号:名称:价格");
//将商品信息输出到goods.txt
//输出格式 -> 商品编号:商品名称:商品价格
File file = new File(filePath);
//自动关闭流
try (BufferedWriter writer = new BufferedWriter(
new FileWriter(file)
)) {
for (Goods goods : this.goodsMap.values()) {
writer.write(String.format("%s:%s:%.2f\n", goods.getId(), goods.getName(), goods.getPrice()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void load() {
//读取goods.txt中的商品信息,经过处理,存入商品集合
File file = new File(filePath);
try (BufferedReader reader = new BufferedReader(
new FileReader(file)
)) {
String read;
while((read=reader.readLine())!=null){
String[] values=read.split(":");
if(values.length==3){
Goods good=new Goods(values[0],values[1],Double.parseDouble(values[2]));
this.addGoods(good);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.qqy.newcheck.impl;
import com.qqy.newcheck.Goods;
import com.qqy.newcheck.GoodsCenter;
import com.qqy.newcheck.OrderCenter;
import com.qqy.newcheck.Order;
import java.io.*;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
/**
* Author:qqy
*/
public class OrderCenterImpl implements OrderCenter {
private GoodsCenter goodsCenter;
public OrderCenterImpl(GoodsCenter goodsCenter) {
this.goodsCenter = goodsCenter;
}
//创建订单集合,key -> 订单编号,value -> 订单信息
private final Map orderMap = new HashMap<>();
private String filePath = System.getProperty("user.dir") + File.separator + "order.txt";
@Override
public void addOrder(Order order) {
this.orderMap.put(order.getOrderId(), order);
}
@Override
public void removeOrder(String orderId) {
this.orderMap.remove(orderId);
}
@Override
public String ordersTable() {
StringBuilder str = new StringBuilder();
str.append("=================所有订单=================\n");
str.append("\t编号\t\t\t总价\n");
for (Order order : this.orderMap.values()) {
Map totalOrder = order.getOrderInfo();
double everyPrice = 0.0;
//商品集合,key -> 商品编号,value -> 商品数量
for (Map.Entry entry : totalOrder.entrySet()) {
String goodId = entry.getKey();
Integer goodCount = entry.getValue();
Goods good = goodsCenter.getGoods(goodId);
everyPrice += good.getPrice() * goodCount;
str.append("\t" + goodId + "\t\t\t" + everyPrice + "\n");
}
str.append("=========================================\n");
}
return str.toString();
}
@Override
public String orderTable(String orderId) {
Order order = this.orderMap.get(orderId);
StringBuilder str = new StringBuilder();
str.append("=================订单信息=================\n");
str.append("编号:" + order.getOrderId() + "\n");
str.append("打印时间:" + LocalDate.now().toString()+"\n");
str.append("=========================================\n");
str.append("编号\t\t\t名称\t\t\t数量\t\t\t单价\n");
double totalPrice = 0.0;
for (Map.Entry entry : order.getOrderInfo().entrySet()) {
Goods good = goodsCenter.getGoods(entry.getKey());
str.append("" + good.getId() + "\t\t\t" + good.getName() + "\t\t\t"+entry.getValue()+"\t\t\t"+ good.getPrice() + "\n");
totalPrice += entry.getValue() * good.getPrice();
}
str.append("=========================================\n");
str.append("总价:" + totalPrice + "\n");
str.append("=========================================\n");
return str.toString();
}
@Override
public void storeOrders() {
System.out.println("保存所有订单到文件,每个订单信息 -> 编号和总价");
//将所有订单信息保存至order.txt
//输出格式 -> 编号:总价
File file = new File(filePath);
try (BufferedWriter writer = new BufferedWriter(
new FileWriter(file)
)) {
for(Order order:this.orderMap.values()){
double totalPrice = 0.0;
for (Map.Entry entry : order.getOrderInfo().entrySet()) {
totalPrice += entry.getValue() *goodsCenter.getGoods(entry.getKey()).getPrice();
}
writer.write(String.format("%s:%.2f\n",order.getOrderId(),totalPrice));
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String loadOrders() {
File file = new File(filePath);
StringBuilder str = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new FileReader(file)
)) {
String read;
if ((file.length() == 0)){
System.out.println("请先保存订单信息!!!");
}else{
System.out.println("加载文件中的订单信息...");
double price;
str.append("=================所有订单=================\n");
str.append("\t编号\t\t\t总价\n");
while ((read = reader.readLine()) != null) {
String[] values = read.split(":");
if (values.length == 2) {
Order order = new Order(values[0]);
price = Double.parseDouble(values[1]);
this.addOrder(order);
str.append("\t" + order.getOrderId() + "\t\t\t" + price + "\n");
}
}
str.append("=========================================\n");
}
} catch (IOException e) {
e.printStackTrace();
}
return str.toString();
}
@Override
public void cleanOrders() {
File file = new File(filePath);
try (FileWriter fileWriter = new FileWriter(file)
) {
fileWriter.write("");
fileWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.qqy.newcheck;
import com.qqy.newcheck.impl.GoodsCenterImpl;
import com.qqy.newcheck.impl.OrderCenterImpl;
import java.util.Scanner;
/**
* 字符界面收银台(优化版)
* Author:qqy
*/
public class CheckStand {
private static Scanner scanner = new Scanner(System.in);
//商品中心管理
private static GoodsCenter goodsCenter = new GoodsCenterImpl();
//订单中心管理,先实例化商品中心,因为订单中心的实例化需要传一个商品中心的实例化对象
private static OrderCenter orderCenter = new OrderCenterImpl(goodsCenter);
private static Integer orderId = 0;
public static void helpInfo() {
System.out.println("*************** 欢迎使用简易收银台 *****************");
System.out.println(" [U] 使用 [S] 设置 [P] 保存所有信息 [A] 关于 [Q] 退出 ");
System.out.println(" 输入: U S P A Q 进入操作 ");
System.out.println("*************************************************");
}
public static void quit() {
System.out.println("*************************************************");
System.out.println(" 欢迎使用,下次再见 ");
System.out.println("*************************************************");
System.exit(0);
}
public static void about() {
System.out.println("******************** 关于 ***********************");
System.out.println(" 名称:简易收银台 ");
System.out.println(" 功能:基于字符界面的收银台操作系统 ");
System.out.println(" 作者: qqy ");
System.out.println(" 版本: v1.0.0 ");
System.out.println(" 意见反馈:*********@qq.com ");
System.out.println("*************************************************");
}
public static void usageInfo() {
System.out.println("******************* 买单功能 ********************");
System.out.println(" [S] 查看当前订单 [U] 查看所有订单 [A] 下单 [C]清空 ");
System.out.println(" [D] 取消 [L] 浏览商品 [P] 保存订单 [R] 返回 ");
System.out.println(" 输入: S U A C D L P R 进入操作 ");
System.out.println("*************************************************");
}
public static void settingInfo() {
System.out.println("******************* 设置功能 ********************");
System.out.println(" [S] 查看 [A] 上架 [D] 下架 ");
System.out.println(" [U] 修改 [P] 保存商品 [R] 返回 ");
System.out.println(" 输入: S A D U P R 进入操作 ");
System.out.println("*************************************************");
}
public static void usage() {
//创建订单,并且添加到订单管理中心
Order order = new Order(String.valueOf(++orderId));
orderCenter.addOrder(order);
usageInfo();
System.out.println(orderCenter.orderTable(order.getOrderId()));
while (true) {
String line = scanner.nextLine();
switch (line.trim().toUpperCase()) {
case "S": {
System.out.println(orderCenter.orderTable(order.getOrderId()));
break;
}
case "A": {
System.out.println("请输入下单信息[编号 数量](如下格式:1 2 ):");
String value = scanner.nextLine().trim();
String[] infoArray = value.split(" ");
if (infoArray.length == 2) {
Goods goods = goodsCenter.getGoods(infoArray[0].trim());
if (goods != null) {
order.add(infoArray[0].trim(), Integer.parseInt(infoArray[1].trim()));
System.out.println(orderCenter.orderTable(order.getOrderId()));
break;
}
}
if (!(goodsCenter.isExistGoods(infoArray[0]))) {
System.out.println("!商品还未上架,请重新选择商品");
}
System.out.println("请按照格式要求输入信息");
break;
}
case "D": {
System.out.println("请输入取消信息[编号 数量](如下格式:1 2 ):");
String value = scanner.nextLine().trim();
String[] infoArray = value.split(" ");
if (infoArray.length == 2) {
Goods goods = goodsCenter.getGoods(infoArray[0].trim());
if (goods != null) {
order.cancel(infoArray[0], Integer.parseInt(infoArray[1].trim()));
System.out.println(orderCenter.orderTable(order.getOrderId()));
break;
}
}
System.out.println("请按照格式要求输入信息");
break;
}
case "U": {
System.out.println(orderCenter.loadOrders());
break;
}
case "L": {
System.out.println(goodsCenter.listGoods());
break;
}
case "C":{
order.clear();
break;
}
case "P": {
//订单信息保存
orderCenter.storeOrders();
break;
}
case "R": {
return;
}
default: {
usageInfo();
}
}
}
}
public static void setting() {
settingInfo();
while (true) {
String line = scanner.nextLine();
switch (line.toUpperCase()) {
case "S": {
System.out.println(goodsCenter.listGoods());
break;
}
case "A": {
System.out.println("请输入上架商品信息(如下格式:1 餐巾纸 1.4):");
Goods goods = readGoods(true);
if (goods == null) {
System.out.println("!请按照格式要求输入信息");
break;
}
if (goodsCenter.isExistGoods(goods.getId())) {
System.out.println("!上架商品已经存在,请重新上架");
} else {
goodsCenter.addGoods(goods);
}
System.out.println(goodsCenter.listGoods());
break;
}
case "D": {
System.out.println("请输入下架商品信息编号(如下格式:1 ):");
Goods goods = readGoods(false);
if (goods == null) {
System.out.println("!请输入存在的商品");
break;
}else{
goodsCenter.removeGoods(goods.getId());
}
System.out.println(goodsCenter.listGoods());
break;
}
case "U": {
System.out.println("请输入修改商品信息(如下格式:1 餐巾纸 1.4 )");
Goods goods = readGoods(false);
if (goods == null) {
System.out.println("!请输入存在的商品");
break;
}else {settingInfo();
goodsCenter.updateGoods(goods);
}
System.out.println(goodsCenter.listGoods());
break;
}
case "P": {
//商品信息保存
goodsCenter.store();
break;
}
case "R": {
return;
}
default: {
settingInfo();
}
}
}
}
public static Goods readGoods(boolean flag) {
String value = scanner.nextLine();
String[] infoArray = value.split(" ");
if (infoArray.length == 3 || infoArray.length == 1) {
if (infoArray.length == 3) {
if (!(CheckStand.isNumber(infoArray[0].trim())&&CheckStand.isNumber(infoArray[2].trim()))){
System.out.println("!商品编号或单价有误,请重新输入");
}else {
if (!flag) {
if (goodsCenter.isExistGoods(infoArray[0])) {
Goods goods = new Goods(infoArray[0], infoArray[1], Double.parseDouble(infoArray[2]));
return goods;
}
}
else{
Goods goods = new Goods(infoArray[0], infoArray[1], Double.parseDouble(infoArray[2]));
return goods;
}
}
}
//infoArray.length == 1
if (!(CheckStand.isNumber(infoArray[0].trim()))){
System.out.println("!商品编号有误,请重新输入");
}else{
if(goodsCenter.isExistGoods(infoArray[0])){
Goods goods = new Goods(infoArray[0], "", 0.0D);
return goods;
}
}
}
return null;
}
public static boolean isNumber(String str) {
for (int i = str.length(); --i >= 0; ) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
public static void main(String[] args) {
helpInfo();
goodsCenter.load();
//每次打开项目,清空订单记录
//新下单后存储信息后,才可查看所有订单。
orderCenter.cleanOrders();
while (true) {
String line = scanner.nextLine();
switch (line.trim().toUpperCase()) {
case "U":
usage();
helpInfo();
break;
case "S":
setting();
helpInfo();
break;
case "A":
about();
break;
case "P":
goodsCenter.store();
orderCenter.storeOrders();
break;
case "Q":
quit();
break;
default:
helpInfo();
}
}
}
}