实验内容
同学们应该都去麦当劳或肯德基吃过快餐吧?请同学们参考肯德基官网的信息模拟肯德基快餐店的收银系统,合理使用C++或Java或Python结合设计模式(2种以上)至少实现系统的以下功能:
1.正常餐品结算和找零。
2.基本套餐结算和找零。
3.使用优惠劵购买餐品结算和找零。
4.可在一定时间段参与店内活动(自行设计或参考官网信息)。
5.模拟打印小票的功能(写到文件中)。
基本要求:
1.程序设计风格良好,控制台界面友好,最多两人一组完成任务。
2.实现功能测试代码,确保程序的健壮性。
3.画出使用的设计模式图。
提高要求:
1.实现可视化界面(使用MFC)。
2.实现会员储值卡功能,完成储值卡消费。
3.实现当天营业额和餐品销量计算和统计,用数据库记录。
算法设计思路
(1)创建两个接口SingleFood和KFC_Factory,分别为单品接口和工厂接口。
(2)创建保存食物信息的抽象类FoodID。
(3)正常餐品:抽象类Hambuger、Snack、Drink、Rice分别继承FoodID类,用于保存食物单价、数量及总价;同时将SingleFood作为接口,其中包含打印食物信息的方法。
(4)基本套餐:抽象类SetFood管理套餐类,同样继承FoodID类,并将SingleFood作为接口。
(5)正常餐品和基本套餐的单品(子类)直接继承Hambuger、Snack、Drink、Rice、SetFood类,给出名称和价格。
(6)创建具体工厂类CKFC_Factory实现工厂接口KFC_Factory,实现具体食物。
(7)创建职员类Clerk管理订购食物。
创建Custom类具体实现点餐功能,并实现使用优惠劵购买餐品结算和找零、店内活动、打印小票等功能。
设计模式图
工厂类和点餐类:
单品类和套餐类:
代码
SingleFood.java
package kkfc;
public interface SingleFood {
// 单品接口
public String outPut(); // 单品接口的抽象方法,用来打印输出单品食物的信息
}
FoodID.java
package kkfc;
// 保存食物信息的抽象类
abstract class FoodID{
public String FoodName; // 食物名称
public double price; // 食物单价
public int num; // 顾客购买该食物的数量
// 计算该餐品的总价
public double totalPrice() {
return price*num;
}
}
Hamburger.java
package kkfc;
//抽象父类Hamburger
abstract class Hamburger extends FoodID implements SingleFood{
public String outPut() {
return ("--"+this.FoodName+"\t单价:"+this.price+"\t数量:"+this.num+"\t总价:"+this.totalPrice()+"元");
}
}
//子类柚香鸡腿堡继承抽象父类Hamburger
class Hamburger_1 extends Hamburger{
public Hamburger_1(int num) {
this.FoodName = "柚香鸡腿堡";
this.price = 19;
this.num = num;
}
}
//子类芝士培根澳牛堡继承抽象父类Hamburger
class Hamburger_2 extends Hamburger{
public Hamburger_2(int num) {
this.FoodName = "芝士培根澳牛堡";
this.price = 25;
this.num = num;
}
}
//子类牛油果香辣鸡腿堡继承抽象父类Hamburger
class Hamburger_3 extends Hamburger{
public Hamburger_3(int num) {
this.FoodName = "牛油果香辣鸡腿堡";
this.price = 17;
this.num = num;
}
}
Snack.java
package kkfc;
//抽象父类Snack(小食类)
abstract class Snack extends FoodID implements SingleFood{
public String outPut() {
return ("--"+this.FoodName+"\t单价:"+this.price+"\t数量:"+this.num+"\t总价:"+this.totalPrice()+"元");
}
}
//子类香辣黄金鸡柳继承抽象父类Snack
class Snack_1 extends Snack{
public Snack_1(int num) {
this.FoodName = "香辣黄金鸡柳";
this.price = 9.9;
this.num = num;
}
}
//子类小鲜肉酥饼继承抽象父类Snack
class Snack_2 extends Snack{
public Snack_2(int num) {
this.FoodName = "小鲜肉酥饼";
this.price = 8;
this.num = num;
}
}
//子类上校鸡块继承抽象父类Snack
class Snack_3 extends Snack{
public Snack_3(int num) {
this.FoodName = "上校鸡块";
this.price = 7;
this.num = num;
}
}
Drink.java
package kkfc;
//抽象父类Drink
abstract class Drink extends FoodID implements SingleFood{
public String outPut() {
return ("--"+this.FoodName+"\t单格:"+this.price+"\t数量:"+this.num+"\t总价:"+this.totalPrice()+"元");
}
}
//子类桃之恋乌龙茶继承抽象父类Drink
class Drink_1 extends Drink{
public Drink_1(int num) {
this.FoodName = "桃之恋乌龙茶";
this.price = 13.5;
this.num = num;
}
}
//子类葡萄柚鲜果莫吉托继承抽象父类Drink
class Drink_2 extends Drink{
public Drink_2(int num) {
this.FoodName = "葡萄柚鲜果莫吉托";
this.price = 14;
this.num = num;
}
}
Rice.java
package kkfc;
//抽象类Rice
abstract class Rice extends FoodID implements SingleFood{
public String outPut() {
return ("--"+this.FoodName+"\t单格:"+this.price+"\t数量:"+this.num+"\t总价:"+this.totalPrice()+"元");
}
}
//子类新奥尔良烤鸡腿饭继承抽象父类Rice
class Rice_1 extends Rice{
public Rice_1(int num) {
this.FoodName = "新奥尔良烤鸡腿饭";
this.price = 19.5;
this.num = num;
}
}
//子类培根蘑菇鸡柳饭继承抽象父类Rice
class Rice_2 extends Rice{
public Rice_2(int num) {
this.FoodName = "培根蘑菇鸡柳饭";
this.price = 20;
this.num = num;
}
}
SetFood.java
package kkfc;
//抽象套餐类
abstract class SetFood extends FoodID implements SingleFood{
public String outPut() {
return ("--"+this.FoodName+"\t单价:"+this.price+"\t数量:"+this.num+"\t总价:"+this.totalPrice()+"元");
}
}
//子类套餐A继承父类抽象套餐
class SetFoodA extends SetFood{
public SetFoodA(int num) {
this.FoodName = "套餐A";
this.price = 32;
this.num = num;
}
}
//子类套餐B继承父类抽象套餐
class SetFoodB extends SetFood{
public SetFoodB(int num) {
this.FoodName = "套餐B";
this.price = 33;
this.num = num;
}
}
//子类套餐C继承父类抽象套餐
class SetFoodC extends SetFood{
public SetFoodC(int num) {
this.FoodName = "套餐C";
this.price = 38;
this.num = num;
}
}
KFC_Factory.java
package kkfc;
//创建KFC工厂接口,生产抽象食物
interface KFC_Factory{
public Hamburger createHamburger(int kind, int num); // 生产抽象汉堡
public Snack createSnack(int kind, int num); // 生产抽象小食
public Drink createDrink(int kind, int num); // 生产抽象饮品
public Rice createRice(int kind, int num); // 生产抽象主食
public SetFood createSetFood(int kind, int num); // 生产抽象套餐
}
CKFC_Factory.java
package kkfc;
//创建具体工厂类实现KFC工厂接口,生产具体食物
class CKFC_Factory implements KFC_Factory{
// 生产具体汉堡
public Hamburger createHamburger(int kind, int num) {
switch(kind)
{
case 1: // 柚香鸡腿堡
return new Hamburger_1(num);
case 2: // 芝士培根澳牛堡
return new Hamburger_2(num);
case 3: // 牛油果香辣鸡腿堡
return new Hamburger_3(num);
default:
return null;
}
}
// 生产具体小食
public Snack createSnack(int kind, int num) {
switch(kind)
{
case 1: // 香辣黄金鸡柳
return new Snack_1(num);
case 2: // 小鲜肉酥饼
return new Snack_2(num);
case 3: // 上校鸡块
return new Snack_3(num);
default:
return null;
}
}
// 生产具体饮品
public Drink createDrink(int kind, int num) {
switch(kind)
{
case 1: // 桃之恋乌龙茶
return new Drink_1(num);
case 2: // 葡萄柚鲜果莫吉托
return new Drink_2(num);
default:
return null;
}
}
// 生产具体主食
public Rice createRice(int kind, int num) {
switch(kind)
{
case 1: // 新奥尔良烤鸡腿饭
return new Rice_1(num);
case 2: // 培根蘑菇鸡柳饭
return new Rice_2(num);
default:
return null;
}
}
// 生产具体套餐
public SetFood createSetFood(int kind, int num) {
switch(kind)
{
case 1: // 套餐A
return new SetFoodA(num);
case 2: // 套餐B
return new SetFoodB(num);
case 3: // 套餐C
return new SetFoodC(num);
default:
return null;
}
}
}
Clerk.java
package kkfc;
//创建职员类
class Clerk{
private KFC_Factory factory_1;
public String s[] = new String[5];
// 构造方法将肯德基抽象工厂传入
public Clerk(KFC_Factory factory_1) {
this.factory_1 = factory_1;
}
// 订购汉堡
public double orderHamburger(int kind, int num) {
Hamburger hamburger = factory_1.createHamburger(kind, num);
hamburger.outPut();
s[0] = hamburger.outPut();
return hamburger.totalPrice();
}
// 订购小食
public double orderSnack(int kind, int num) {
Snack snack = factory_1.createSnack(kind, num);
snack.outPut();
s[1] = snack.outPut();
return snack.totalPrice();
}
// 订购饮品
public double orderDrink(int kind, int num) {
Drink drink = factory_1.createDrink(kind, num);
drink.outPut();
s[2] = drink.outPut();
return drink.totalPrice();
}
// 订购主食
public double orderRice(int kind, int num) {
Rice rice = factory_1.createRice(kind, num);
rice.outPut();
s[3] = rice.outPut();
return rice.totalPrice();
}
// 订购套餐
public double orderSetFood(int kind, int num) {
SetFood setFood = factory_1.createSetFood(kind, num);
setFood.outPut();
s[4] = setFood.outPut();
return setFood.totalPrice();
}
}
Custom.java
package kkfc;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;
//实现具体的订购
public class Custom {
static CKFC_Factory factory= new CKFC_Factory(); // 创建KFC工厂
static Clerk customer = new Clerk(factory); // 创建顾客
static int type; // 顾客选择餐品类别
static int kind; // 顾客选择该类别下的具体餐品
static int num; // 顾客选择餐品数量
/* 实现单品点餐功能 */
public static void orderSingleFood() throws ParseException, FileNotFoundException {
double total = 0; // 顾客所点单品总价
double total_1 = 0;
double total_2 = 0;
double total_3 = 0;
double total_4 = 0;
int flag = 1;
while(flag==1)
{
Scanner sc = new Scanner(System.in);
System.out.println("请选择餐品类别:");
type = sc.nextInt();
System.out.println("请选择该类别下的具体餐品:");
kind = sc.nextInt();
System.out.println("请输入餐品个数:");
num = sc.nextInt();
switch(type)
{
case 1:
total_1 = customer.orderHamburger(kind, num);
break;
case 2:
total_2 = customer.orderSnack(kind, num);
break;
case 3:
total_3 = customer.orderDrink(kind, num);
break;
case 4:
total_4 = customer.orderRice(kind, num);
break;
default:
System.out.println("对不起,没有该类餐品,请重新选择!");
}
System.out.println("继续点餐请选1,结束点餐请选0:");
flag = sc.nextInt();
}
total = total_1 + total_2 + total_3 + total_4;
// 获取系统时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd : hh:mm:ss");
// 将系统当前时间与活动时间进行比较,判断是否参与活动
int huodong = 0; // 活动
Date date_1 = new Date();
Date date_2 = new Date();
date_1 = dateFormat.parse("2020-5-11 : 24:00:00");
date_2 = dateFormat.parse("2020-6-22 : 24:00:00");
if((date_1.getTime()<date.getTime()) & (date.getTime()<date_2.getTime()))
huodong = 5;
else
huodong = 0;
Scanner sc = new Scanner(System.in);
System.out.println("餐品总价:"+total);
System.out.println("请输入付款金额:");
double fukuan = sc.nextInt();
// 使用优惠券结算
int youhui = 0;
System.out.println("使用优惠券付款请输入1,不使用请输入0");
int temp = sc.nextInt();
if(temp==1)
{
System.out.println("请输入优惠券额度:");
youhui = sc.nextInt();
System.out.println("----------------欢迎光临KFC----------------");
System.out.println("账单如下:");
int i=0;
for(i=0; i<5; i++)
System.out.println(customer.s [i]);
System.out.println("本次消费总金额:"+total);
System.out.println("优惠券额度:"+youhui);
System.out.println("共收您金额:"+fukuan);
if(huodong==5)
System.out.println("目前本店正处于店庆期间,凡购买本店餐品者均立减五元");
else
System.out.println("本店暂无活动");
System.out.println("找零:"+(fukuan-(total-youhui-huodong)));
System.out.println(dateFormat.format(date));
System.out.println("---------------------------------------");
PrintStream ps = new PrintStream("D:\\eclipse-workspace\\kkfc\\KFC Receipt.txt");
System.setOut(ps);
System.out.println("----------------欢迎光临KFC----------------");
System.out.println("账单如下:");
int j=0;
for(j=0; j<5; j++)
System.out.println(customer.s [j]);
System.out.println("本次消费总金额:"+total);
System.out.println("优惠券额度:"+youhui);
System.out.println("共收您金额:"+fukuan);
if(huodong==5)
System.out.println("目前本店正处于店庆期间,凡购买本店餐品者均立减五元");
else
System.out.println("本店暂无活动");
System.out.println("找零:"+(fukuan-(total-youhui-huodong)));
System.out.println(dateFormat.format(date));
System.out.println("---------------------------------------");
}
else
{
System.out.println("----------------欢迎光临KFC----------------");
System.out.println("账单如下:");
int i=0;
for(i=0; i<5; i++)
System.out.println(customer.s [i]);
System.out.println("本次消费总金额:"+total);
System.out.println("共收您金额:"+fukuan);
if(huodong==5)
System.out.println("目前本店正处于店庆期间,凡购买本店餐品者均立减五元");
else
System.out.println("本店暂无活动");
System.out.println("找零:"+(fukuan-(total-huodong)));
System.out.println(dateFormat.format(date));
System.out.println("--------------------------------------");
PrintStream ps = new PrintStream("D:\\eclipse-workspace\\kkfc\\KFC Receipt.txt");
System.setOut(ps);
System.out.println("----------------欢迎光临KFC----------------");
System.out.println("账单如下:");
int k=0;
for(k=0; k<5; k++)
System.out.println(customer.s [k]);
System.out.println("本次消费总金额:"+total);
System.out.println("共收您金额:"+fukuan);
if(huodong==5)
System.out.println("目前本店正处于店庆期间,凡购买本店餐品者均立减五元");
else
System.out.println("本店暂无活动");
System.out.println("找零:"+(fukuan-(total-huodong)));
System.out.println(dateFormat.format(date));
System.out.println("--------------------------------------");
}
}
/* 实现套餐点餐功能 */
public static void orderSetFood() throws ParseException, FileNotFoundException {
double total; // 顾客所点套餐总价
double total_1 = 0;
double total_2 = 0;
double total_3 = 0;
int flag = 1;
while(flag==1)
{
Scanner sc = new Scanner(System.in);
System.out.println("请选择套餐类别:");
kind = sc.nextInt();
System.out.println("请选择套餐数量:");
num = sc.nextInt();
switch(kind)
{
case 1:
total_1 = customer.orderSetFood(kind, num);
break;
case 2:
total_2 = customer.orderSetFood(kind, num);
break;
case 3 :
total_3 = customer.orderSetFood(kind, num);
break;
default:
System.out.println("对不起,没有该类套餐,请重新选择!");
}
System.out.println("继续点餐请选1,结束点餐请选0:");
flag = sc.nextInt();
}
total = total_1 + total_2 + total_3;
// 获取系统时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd : hh:mm:ss");
// 将系统当前时间与活动时间进行比较,判断是否参与活动
int huodong = 0; // 活动
Date date_1 = new Date();
Date date_2 = new Date();
date_1 = dateFormat.parse("2019-5-11 : 24:00:00");
date_2 = dateFormat.parse("2019-6-22 : 24:00:00");
if((date_1.getTime()<date.getTime()) & (date.getTime()<date_2.getTime()))
huodong = 5;
else
huodong = 0;
Scanner sc = new Scanner(System.in);
System.out.println("餐品总价:"+total);
System.out.println("请输入付款金额:");
double fukuan = sc.nextInt();
// 使用优惠券结算
int youhui = 0;
System.out.println("使用优惠券付款请输入1,不使用请输入0");
int temp = sc.nextInt();
if(temp==1)
{
System.out.println("请输入优惠券额度:");
youhui = sc.nextInt();
System.out.println("----------------欢迎光临KFC----------------");
System.out.println("账单如下:");
int i=0;
for(i=0; i<5; i++)
System.out.println(customer.s [i]);
System.out.println("本次消费总金额:"+total);
System.out.println("优惠券额度:"+youhui);
System.out.println("共收您金额:"+fukuan);
if(huodong==5)
System.out.println("目前本店正处于店庆期间,凡购买本店餐品者均立减五元");
else
System.out.println("本店暂无活动");
System.out.println("找零:"+(fukuan-(total-youhui-huodong)));
System.out.println(dateFormat.format(date));
System.out.println("--------------------------------------");
PrintStream ps = new PrintStream("D:\\eclipse-workspace\\kkfc\\KFC Receipt.txt");
System.setOut(ps);
System.out.println("----------------欢迎光临KFC----------------");
System.out.println("账单如下:");
int j=0;
for(j=0; j<5; j++)
System.out.println(customer.s [j]);
System.out.println("本次消费总金额:"+total);
System.out.println("优惠券额度:"+youhui);
System.out.println("共收您金额:"+fukuan);
if(huodong==5)
System.out.println("目前本店正处于店庆期间,凡购买本店餐品者均立减五元");
else
System.out.println("本店暂无活动");
System.out.println("找零:"+(fukuan-(total-youhui-huodong)));
System.out.println(dateFormat.format(date));
System.out.println("--------------------------------------");
}
else
{
System.out.println("----------------欢迎光临KFC----------------");
System.out.println("账单如下:");
int i=0;
for(i=0; i<5; i++)
System.out.println(customer.s [i]);
System.out.println("本次消费总金额:"+total);
System.out.println("共收您金额:"+fukuan);
if(huodong==5)
System.out.println("目前本店正处于店庆期间,凡购买本店餐品者均立减五元");
else
System.out.println("本店暂无活动");
System.out.println("找零:"+(fukuan-(total-huodong)));
System.out.println(dateFormat.format(date));
System.out.println("--------------------------------------");
PrintStream ps = new PrintStream("D:\\eclipse-workspace\\kkfc\\KFC Receipt.txt");
System.setOut(ps);
System.out.println("----------------欢迎光临KFC----------------");
System.out.println("账单如下:");
int k=0;
for(k=0; k<5; k++)
System.out.println(customer.s [k]);
System.out.println("本次消费总金额:"+total);
System.out.println("共收您金额:"+fukuan);
if(huodong==5)
System.out.println("目前本店正处于店庆期间,凡购买本店餐品者均立减五元");
else
System.out.println("本店暂无活动");
System.out.println("找零:"+(fukuan-(total-huodong)));
System.out.println(dateFormat.format(date));
System.out.println("--------------------------------------");
}
}
public static void main(String[] args) throws ParseException, FileNotFoundException {
Menu menu = new Menu();
System.out.println("欢迎光临KFC,很高兴为您服务!");
System.out.println("\n单品请选择0,套餐请选择1:");
int flag;
Scanner sc = new Scanner(System.in);
flag = sc.nextInt();
switch(flag)
{
case 0:
orderSingleFood();
break;
case 1:
orderSetFood();
break;
default:
System.out.println("对不起,您的选择错误,请重新选择!");
}
}
}
测试、调试以及运行结果
测试用例:
测试用例1:
测试用例2
测试用例3
测试用例4
打印小票测试,如图:
(以测试用例5为例)
总结
1.在这次作业中,巩固了前段时间学习的Java知识,尤其是接口和继承的区别,一个类可以有多个接口,但子类只能继承一个父类;某个接口被类是实现时,必须重新定义接口中的所有抽象方法,而继承想调用哪个方法直接调用即可。
2.体现了设计模式中的开闭原则和依赖倒转原则。在需要添加新的产品的情况下,可以直接对模块进行扩展(开闭原则);各个子类依赖于抽象接口,不依赖于具体实现,如生产单品和套餐的类均依赖于工厂接口KFC_Factory,而不直接依赖于工厂实现类CKFC_Factory(依赖倒转原则)。
参考: https://blog.csdn.net/weixin_44361543/article/details/90143757