java实现kfc点餐系统
1.基本需求
1.正常餐品结算和找零。
2.基本套餐结算和找零。
3.使用优惠劵购买餐品结算和找零。
4.可在一定时间段参与店内活动(自行设计或参考官网信息)。
5.模拟打印小票的功能(写到文件中)。
6.html.jsp实现可视化界面。
7.实现会员储值卡功能,完成储值卡消费。
8.实现当天营业额和餐品销量计算和统计,用数据库记录。Echars实现数据可视化
2.设计模式
单点食物:
- 采用简单工厂,使用反射实现食品类的实例化
- 工厂类 (SimFoodFactory)
套餐食物:
- 采用抽象工厂,生成套餐系列产品(三个套餐)
- 工厂类(ComboOneFactory ComboTwoFactory ComboThreeFactory )
数据库连接池
- 采用单例模式,创建c3p0数据库连接池对象。
类图如下所示
3.实现
实体类
public class Food {
public Integer id;//id
public String name;//食品名
public Double price;//食品价格
}
Drink类在Food类上的基础上有了容量属性
public class Drink extends Food{
public Float capacity;
}
Eat类在Food类的基础上有了质量属性
public class Eat extends Food {
public Float quailty;
}
汉堡类继承Eat类
public class HamBean extends Eat {
public HamBean() {
this.id = 1;
this.name = "汉堡";
this.price = 12.0;
this.quailty = 10f;
}
}
薯条类继承Eat类
public class ChipsBean extends Eat {
public ChipsBean() {
this.id = 3;
this.name = "薯条";
this.price = 8.0;
this.quailty = 50f;
}
}
炸鸡类继承Eat类
public class ChickenBean extends Eat {
public ChickenBean() {
this.id = 2;
this.name = "炸鸡";
this.price = 25.0;
this.quailty = 100f;
}
}
可乐类继承Drink类
public class ColaBean extends Drink {
public ColaBean() {
this.id = 1;
this.name = "可乐";
this.price = 8.0;
this.capacity = 100f;
}
}
咖啡类继承Drink类
public class CafeBean extends Drink{
public CafeBean() {
this.id = 2;
this.name = "咖啡";
this.price = 12.0;
this.capacity = 100f;
}
}
果汁类继承Drink类
public class JuiceBean extends Drink {
public JuiceBean() {
this.id = 2;
this.name = "咖啡";
this.price = 12.0;
this.capacity = 100f;
}
}
简单工厂生产单件产品
/**
* 简单工厂,通过反射加载食物实例(单点)
*/
public class SimFoodFactory {
public Food getFood(Class c) {
try {
return (Food) Class.forName(c.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
抽象工厂实现生产套餐
public interface ComboFactory {
List<Food> getCombo();
}
套餐1
/**
* 1号组合套餐
* 炸鸡和可乐
*/
public class ComboOneFactory implements ComboFactory {
@Override
public List<Food> getCombo() {
List<Food> foodOneList= new ArrayList<Food>();//存储套餐产品
Food chick = new ChickenBean();//实例化套餐内的产品
Food cola = new ColaBean();
chick.price = chick.price-2;//套餐的优惠,炸鸡价格减一元
cola.price = cola.price-1;
foodOneList.add(chick);
foodOneList.add(cola);
return foodOneList;//返回套餐集合
}
}
套餐2
/**
* 2号组合套餐
* 薯条和果汁
*/
public class ComboTwoFactory implements ComboFactory {
@Override
public List<Food> getCombo() {
List<Food> foodTwoList= new ArrayList<Food>();
Food chips = new ChipsBean();
Food juice= new JuiceBean();
chips.price = chips.price-1;//套餐组合的优惠
juice.price = juice.price-0.5;
foodTwoList.add(chips);
foodTwoList.add(juice);
return foodTwoList;
}
}
套餐3
/**
* 3号组合套餐
* 汉堡和咖啡
*/
public class ComboThreeFactory implements ComboFactory {
@Override
public List<Food> getCombo() {
List<Food> foodThreeList= new ArrayList<Food>();
Food ham = new HamBean();
Food cafe= new CafeBean();
ham.price = ham.price-1;//套餐组合的优惠
cafe.price = cafe.price-0.5;
foodThreeList.add(cafe);
foodThreeList.add(ham);
return foodThreeList;
}
}
数据库连接池对象
public class DaoUtils {
private static DataSource dataSource;
public static DataSource getDataSource() {
if(dataSource==null)
dataSource = new ComboPooledDataSource();
return dataSource;
}
}
数据库连接池配置
<?xml version ="1.0" encoding= "UTF-8" ?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/kfc?useUnicode=true&characterEncoding=UTF8</property>
<property name="user">root</property>
<property name="password">root</property>
</default-config>
</c3p0-config>
数据库相关实现
关于出售商品
public class BussDao {
/**
*
* @param name 商品名字
* @param count 商品数量
* @throws SQLException
*/
public void upDateBuss(String name,int count ) throws SQLException {
DataSource dataSource = DaoUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "update bussiness set count="+count+" where name=?";
queryRunner.update(sql,name);
}
/**
*
* @param name 商品名字
* @return 返回该商品的已出售的数量
* @throws SQLException
*/
public int selectCountByName(String name) throws SQLException {
DataSource dataSource = DaoUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "select count from bussiness where name=?";
List<BusinessBean> bus = (List<BusinessBean>)queryRunner.query(sql, name, new BeanListHandler(BusinessBean.class));
return bus.get(0).getCount();
}
/**
* 查找卖货信息
* @return
* @throws SQLException
*/
public List<BusinessBean> selectBus() throws SQLException {
DataSource dataSource = DaoUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "select * from bussiness ";
List<BusinessBean> bus = (List<BusinessBean>)queryRunner.query(sql, new BeanListHandler(BusinessBean.class));
return bus;
}
/*
获取现在的输入
*/
public Integer selectMony() throws SQLException {
DataSource dataSource = DaoUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "select count from bussiness where name='收入'";
List<BusinessBean> money = (List<BusinessBean>)queryRunner.query(sql, new BeanListHandler(BusinessBean.class));
return money.get(0).getCount();
}
/*
更新收入金额
*/
public void updateMoney(Double count) throws SQLException {
DataSource dataSource = DaoUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "update bussiness set count=? where name='收入'";
queryRunner.update(sql,count);
}
}
关于会员
public class MemberDao {
/**
* 查询会余额
* @param id
* @return 返回会员余额
* @throws SQLException
*/
public Double SelectMemberMoneyById(String id) throws SQLException {
DataSource dataSource = DaoUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "select money from member where id=?";
MemberBean memberBean = (MemberBean) queryRunner.query(sql,id, new BeanHandler(MemberBean.class));
if(memberBean==null)
return -1.0;
return memberBean.getMoney();
}
/**
* 更新会员余额
* @param id
* @param money
* @throws SQLException
*/
public void UpdateMemberMoneyById(String id,Double money) throws SQLException {
DataSource dataSource = DaoUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "update member set money="+money+" where id=?";
queryRunner.update(sql,id);
}
}
业务的实现
关于商品
public class BusinessService {
BussDao bussDao = new BussDao();
/**
* 更新卖货信息
* @param foodList
* @throws SQLException
*/
public void updateBusiness(List<Food> foodList) throws SQLException {
Map <String ,Integer>map = new HashMap();
//统计每个商品出现的次数
for(Food f:foodList){
if(!map.containsKey(f.name))
map.put(f.name,1);
else
map.put(f.name,map.get(f.name)+1);
}
for(String key:map.keySet()) {
//查询该商品已出售的数量
int i = bussDao.selectCountByName(key);
//更新数量
bussDao.upDateBuss(key,i+map.get(key));
}
}
//查找商品的卖出信息
public List<BusinessBean> findBus() throws SQLException {
return bussDao.selectBus();
}
//获取现收入
public Integer getMoney() throws SQLException {
return bussDao.selectMony();
}
//更新收入
public void updateMoney(Double count) throws SQLException {
Integer money = getMoney();
bussDao.updateMoney(money+count);
}
}
关于资金
public class MoneyService {
MemberDao memberDao = new MemberDao();
/**
* 根据商品获得总价钱
* disCount折扣
* tickte优惠券金额
*/
public Double getMoneyCount(List<Food> list,Double disCount,Double ticket){
Double moneyCount=0.0;
for(Food food:list)
moneyCount +=food.price;
return moneyCount*disCount-ticket;
}
/**
*找零
* @param inMoney 收入的钱
* @param count 食物总价钱
* @return 找零的钱
*/
public Double getCoin(Double inMoney,Double count){
return inMoney-count;
}
/**
*打印小票
* @param list 食物集合
* @param disCount 折扣
* @param ticket 优惠券
*/
public void receipt(List<Food> list, Double disCount, Double ticket) throws IOException {
File file = new File("e:/ticket.txt");
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
bw.write("消费清单如下!!"+"\r\n");
for(Food food:list){
bw.write("食物:"+food.name+"\r\n");
bw.write("价格:"+food.price+"元"+"\r\n");
}
bw.write("折扣:"+disCount*10+"折"+"\r\n");
bw.write("优惠:"+ticket+"元"+"\r\n");
bw.write("总金额"+ getMoneyCount(list,disCount,ticket)+"元");
bw.close();
}
/**
* 通过id获取会员
* @param id
* @return
* @throws SQLException
*/
public Double getMemberMoneyById(String id) throws SQLException {
return memberDao.SelectMemberMoneyById(id);
}
public void resetMoneyById(String id,Double money) throws SQLException {
memberDao.UpdateMemberMoneyById(id,money);
}
}
控制层
关于食物的
@WebServlet("/food.action")
public class FoodController extends HttpServlet{
SimFoodFactory simFoodFactory = new SimFoodFactory();
MoneyService moneyService = new MoneyService();
BusinessService bussinessService = new BusinessService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
List<Food> foodList;
//获取表达数据
String colaBean = req.getParameter("ColaBean");
String cafeBean = req.getParameter("CafeBean");
String juiceBean = req.getParameter("JuiceBean");
String chickenBean = req.getParameter("ChickenBean");
String chipsBean = req.getParameter("ChipsBean");
String hamBean = req.getParameter("HamBean");
String disCount = req.getParameter("discount");//折扣
String tickle = req.getParameter("tickle");//优惠券
String com = req.getParameter("com");
switch (com){
case "1":
foodList = new ComboOneFactory().getCombo();
break;
case "2":
foodList = new ComboTwoFactory().getCombo();
break;
case "3":
foodList = new ComboThreeFactory().getCombo();
break;
default: foodList = new ArrayList();
}
if("on".equals(colaBean)) {//可乐
Food food = simFoodFactory.getFood(ColaBean.class);
foodList.add(food);
}
if("on".equals(cafeBean)) {//咖啡
Food food = simFoodFactory.getFood(CafeBean.class);
foodList.add(food);
}
if("on".equals(juiceBean)) {//果汁
Food food = simFoodFactory.getFood(JuiceBean.class);
foodList.add(food);
}
if("on".equals(chickenBean)) {//炸鸡
Food food = simFoodFactory.getFood(ChickenBean.class);
foodList.add(food);
}
if("on".equals(chipsBean)) {//薯条
Food food = simFoodFactory.getFood(ChipsBean.class);
foodList.add(food);
}
if("on".equals(hamBean)) {//汉堡
Food food = simFoodFactory.getFood(HamBean.class);
foodList.add(food);
}
try {
//更新卖货信息
bussinessService.updateBusiness(foodList);
//获取总价钱
Double moneyCount = moneyService.getMoneyCount(foodList, Double.valueOf(disCount), Double.valueOf(tickle));
//更新总价钱
bussinessService.updateMoney(moneyCount);
//打印票
moneyService.receipt(foodList,Double.valueOf(disCount),Double.valueOf(tickle));
req.setAttribute("money",moneyCount);//总价
req.setAttribute("disCount",Double.valueOf(disCount)*10);//折扣
req.setAttribute("tickle",tickle);//优惠券
req.setAttribute("food",foodList);//食物
req.getRequestDispatcher("show.jsp").forward(req,resp);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
关于资金
@WebServlet("/money.action")
public class MoneyConlroller extends HttpServlet {
MoneyService moneyService = new MoneyService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
String inMoney = req.getParameter("inMoney");
String count = req.getParameter("count");
String message;
//计算找零
Double coin = moneyService.getCoin(Double.valueOf(inMoney), Double.valueOf(count));
if(coin >=0 ) {//现金支付
message = "找零" + coin;
resp.getWriter().write(message);
return;
}else{//收钱小鱼需要的钱
message = "资金不足";
resp.getWriter().write(message);
}
}
}
关于会员
@WebServlet("/member.action")
public class MemberController extends HttpServlet{
MoneyService moneyService = new MoneyService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
String memberId = req.getParameter("memberId");
String count = req.getParameter("count");
String message;
try {
//会员的钱
Double memberMoney = moneyService.getMemberMoneyById(memberId);
//会员还剩的钱
Double memberCoin = moneyService.getCoin(memberMoney, Double.valueOf(count));
if(memberMoney==-1.0){
message = "会员不存在";
resp.getWriter().write(message);
return;
}
if(memberCoin<0){
message = "会员账户余额不足";
resp.getWriter().write(message);
return;
}
else {
//更新账户余额
moneyService.resetMoneyById(memberId,Double.valueOf(memberCoin));
message = "扣费成功,还剩:"+moneyService.getMemberMoneyById(memberId);
resp.getWriter().write(message);
return;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Echars
@WebServlet("/info.action")
public class EcharController extends HttpServlet{
BusinessService bs = new BusinessService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
try {
List<BusinessBean> bus = bs.findBus();
//将查找的商品对象转换为JSON字符串
String s = JSON.toJSONString(bus);
resp.getWriter().write(s);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
前端
由于前端页面篇幅过长,在这里给出关键代码
index.html的表单
<form class="layui-form" action="/food.action" style="margin-top: 50px">
<div class="layui-form-item">
<label class="layui-form-label">套餐选择</label>
<div class="layui-input-block">
<select name="com">
<option value=""></option>
<option value="1">套餐1:炸鸡+可乐</option>
<option value="2">套餐2:薯条+果汁</option>
<option value="3">套餐3:汉堡+咖啡</option>
</select>
</div>
</div>
<font style="margin-top: 20px;margin-left: 40px" size="4" face="宋体">单点</font>
<div class="layui-form-item">
<label class="layui-form-label">饮料</label>
<div class="layui-input-block" >
<input type="checkbox" name="ColaBean" title="可乐">
<input type="checkbox" name="CafeBean" title="咖啡">
<input type="checkbox" name="JuiceBean" title="果汁">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">食物 </label>
<div class="layui-input-block">
<input type="checkbox" name="HamBean" title="汉堡">
<input type="checkbox" name="ChickenBean" title="炸鸡">
<input type="checkbox" name="ChipsBean" title="薯条">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">折扣</label>
<div class="layui-input-block">
<input type="text" name="discount" required lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">优惠券</label>
<div class="layui-input-block">
<input type="text" name="tickle" required lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input">
</div>
</div>
<button class="layui-btn" lay-submit lay-filter="formDemo">点餐</button>
</form>
Echars实现数据可视化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="echarts.js"></script>
<script type="text/javascript" src="jquery-1.9.1.js"></script>
</head>
<body onload="f1()">
<div id="main" style="width: 400px;height:400px;" class="layui-col-md4"></div>
<script type="text/javascript">
function f1() {
var myChart = echarts.init(document.getElementById('main'));
$.get('info.action').done(function (data) {
var parseData = JSON.parse(data);
var name = new Array(6);
var count = new Array(6);
for(var i=0;i<parseData.length;i++){
name[i]=parseData[i].name;
count[i]=parseData[i].count;
}
myChart.setOption({
title: {
text: '销量统计'
},
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: name
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: count
}]
});
});
}
</script>
</body>
</html>
显示商品信息
<body>
<div style="height: 400px;width: 400px;margin-left: 400px;margin-top: 200px">
<c:forEach items="${requestScope.food}" var="food">
<h4 >商品名:${food.name}-------价格:${food.price}</h4>
</c:forEach>
<h4 style="color: red">折扣:${disCount}</h4>
<h4 style="color: red">券优惠:${tickle}</h4>
<h4 style="color: red">总价:${money}</h4>
<form id="moneydata" >
收入 <input type="text" name="inMoney">
<br>
<a href="member.jsp?count=${money}">会员</a>
<br>
<input type="hidden" name="count" value="${money}">
<button type="button" onclick="f1()">提交</button>
</form>
<script type="text/javascript">
function f1() {
$.ajax({
"url": "/money.action",
"type": "get",
"data": $("#moneydata").serialize(),
"success": function (data, msg, xhr) {
alert(data);
},
"error": function () {
console.log("失败...");
}
});
}
</script>
</div>
</body>
会员
使用ajax异步提交
<body>
<div style="margin-top: 20%;margin-left: 30%">
<form action="" id="mem">
会员号<input type="text" name="memberId">
<input type="hidden" name="count" value="${param.count}">
<button type="button" onclick="f1()">确认支付 </button>
</form>
</div>
</body>
<script type="text/javascript">
function f1() {
$.ajax({
"url": "/member.action",
"type": "get",
"data": $("#mem").serialize(),
"success": function (data, msg, xhr) {
alert(data);
if(data.toString().charAt(0)=="扣")
$(window).attr("location","index.html");
},
"error": function () {
console.log("失败...");
}
});
}
</script>
运行截图
注:选项中的折扣1表示十折(不打折),0.1表示一折
会员
打印小票
销量数据统计
数据库信息