一.实验目的
1.掌握面向对象程序设计的方法。明确类与对象的概念,掌握面向对象设计七大原则;
2.掌握常见的设计模式以及类图的描述。
二、实验内容
同学们应该都去麦当劳或肯德基吃过快餐吧?请同学们参考肯德基官网的信息模拟肯德基快餐店的收银系统,合理使用C++或Java或Python结合设计模式(2种以上)至少实现系统的以下功能:
1.正常餐品结算和找零。
2.基本套餐结算和找零。
3.使用优惠劵购买餐品结算和找零。
4.可在一定时间段参与店内活动(自行设计或参考官网信息)。
5.模拟打印小票的功能(写到文件中)。
基本要求:
- 程序设计风格良好,控制台界面友好,最多两人一组完成任务。
- 实现功能测试代码,确保程序的健壮性。
- 画出使用的设计模式图。
提高要求:
- 实现可视化界面(使用MFC)。
- 实现会员储值卡功能,完成储值卡消费。
- 实现当天营业额和餐品销量计算和统计,用数据库记录。
三、题目要求
1.题目分析
本次作业要实现的功能为肯德基的点餐系统。在本次作业中主要使用了工厂方法模式和抽象工厂模式两种模式来编写代码。
① 创建生产具体食物的工厂肯德基店、工厂生产的产品、负责点餐的职员和客户。
②创建生产各种抽象食物的抽象工厂,肯德基店实现这个抽象工厂,生产具体的食品,
③对每个具体的食物添加食物父类。对于每一种食物的属性,使用组合的方式,将抽象工厂作为客户类中的一个实例变量,客户需要任何产品,只须向工厂请求即可。
④对于实现优惠券和一定时间段的活动,询问客户是否有优惠券,并且当总计大于100元时,可以获得本店一张八五折优惠券,活动时间是通过获取系统当前时间,判断是否在活动范围内。
2.设计模式图
3.代码实现
public interface IFood {
void printMesage();//抽象方法,打印输出食物信息
}
public class BaseFood {
// 类别
public String kind;
// 数量
public int num;
// 价格
public int price;
// 合计
public int totalPrice()
{
//计算食品总价
return this.num * this.price;
}
}
//饮料基类
public abstract class Beverage extends BaseFood implements IFood{
//方法重构
public void printMesage()
{
System.out.println("--" + this.kind + "\t\t\t单价:" + this.price +"元"+ "\t\t\t数量:" + this.num + "\t\t\t合计:" + this.totalPrice()+"元");
}
}
//鸡腿基类
public abstract class Chicken extends BaseFood implements IFood{
//方法重构
public void printMesage()
{
System.out.println("--" + this.kind + "\t\t\t单价:" + this.price + "元"+"\t\t\t数量:" + this.num + "\t\t\t合计:" + this.totalPrice()+"元");
}
}
//汉堡基类
public abstract class Hamburger extends BaseFood implements IFood{
//方法重构
public void printMesage()
{
System.out.println("--" + this.kind + "\t\t\t单价:" + this.price +"元"+ "\t\t\t数量:" + this.num + "\t\t\t合计:" + this.totalPrice()+"元");
}
}
//套餐基类
public class Meal extends BaseFood implements IFood{
//方法重构
public void printMesage()
{
System.out.println("--" + this.kind + "\t\t\t单价:" + this.price + "元"+"\t\t\t数量:" + this.num + "\t\t\t合计:" + this.totalPrice()+"元");
}
}
public abstract class FrenchFries extends BaseFood implements IFood{
public void printMesage()
{
System.out.println("--" + this.kind + "风味薯条,\t单价:" + this.price + ",\t数量:" + this.num + ",\t合计:" + this.totalPrice());
}
}
//食物信息
public class ChinaBeverage_1 extends Beverage{//饮料
public ChinaBeverage_1(int num)//构造方法
{
this.kind = "百事可乐(加冰)";
this.price = 5;
this.num = num;
}
}
public class ChinaBeverage_2 extends Beverage{
public ChinaBeverage_2(int num)//构造方法
{
this.kind = "百事可乐(常温)";
this.price = 5;
this.num = num;
}
}
public class ChinaChicken_1 extends Chicken{//鸡
public ChinaChicken_1(int num)//构造方法
{
this.kind = "香辣鸡腿";
this.price = 7;
this.num = num;
}
}
public class ChinaChicken_2 extends Chicken{
public ChinaChicken_2(int num)//构造方法
{
this.kind = "奥尔良鸡腿";
this.price = 6;
this.num = num;
}
}
public class ChinaFrenchFries extends FrenchFries{//薯条
public ChinaFrenchFries(int num)//构造方法
{
this.kind = "豪华版";
this.price = 8;
this.num = num;
}
}
public class ChinaHamburger_1 extends Hamburger{//汉堡包
public ChinaHamburger_1(int num)//构造方法
{
this.kind = "香辣鸡腿堡";
this.price = 9;
this.num = num;
}
}
public class ChinaHamburger_2 extends Hamburger{
public ChinaHamburger_2(int num)//构造方法
{
this.kind = "香辣虾堡";
this.price = 8;
this.num = num;
}
}
public class ChinaMeal_1 extends Meal{
public ChinaMeal_1(int num)//构造方法
{
this.kind = "香辣鸡腿堡+薯条+可乐";
this.price = 33;
this.num = num;
}
}
public class ChinaMeal_2 extends Meal{
public ChinaMeal_2(int num)//构造方法
{
this.kind = "香辣虾堡+奥尔良鸡腿+可乐";
this.price = 30;
this.num = num;
}
}
public interface Factory {
//生产汉堡
public Hamburger createHamburger(int type,int num);
// 生产薯条
public FrenchFries createFrenchFries(int type,int num);
// 生产鸡翅
public Chicken createChicken(int type,int num);
// 生产饮料
public Beverage createBeverage(int type,int num);
//生产套餐
public Meal creatMeal(int type,int num);
}
public class Customer {
private Factory kfc;
//构造方法将抽象工厂作为参数传入
public Customer(Factory kfc)
{
this.kfc = kfc;
}
//订购香辣鸡腿汉堡
public int orderHamburger(int type,int num)
{
//获得香辣鸡腿汉堡
Hamburger hamburger = kfc.createHamburger(type,num);
//输出订购信息
hamburger.printMesage();
//返回总价
return hamburger.totalPrice();
}
//订购奥尔良烤鸡腿
public int orderChicken(int type,int num)
{
//获得奥尔良烤鸡腿
Chicken chicken = kfc.createChicken(type,num);
//输出订购信息
chicken.printMesage();
//返回总价
return chicken.totalPrice();
}
//订购薯条
public int orderFrenchFries(int type,int num)
{
//获得薯条
FrenchFries frenchFries = kfc.createFrenchFries(type,num);
//输出订购信息
frenchFries.printMesage();
//返回总价
return frenchFries.totalPrice();
}
//订购可乐
public int orderBeverage(int type,int num)
{
//获得可乐
Beverage beverage = kfc.createBeverage(type,num);
//输出订购信息
beverage.printMesage();
//返回总价
return beverage.totalPrice();
}
//订购套餐
public int orderMeal(int type,int num){
//获得套餐
Meal setmeal=kfc.creatMeal(type, num);
//返回订购信息
setmeal.printMesage();
//返回总价
return setmeal.totalPrice();
}
}
public class ProductFood implements Factory{
// 生产可乐
public Beverage createBeverage(int type,int num)
{
if(1==type)//可乐加冰
return new ChinaBeverage_1(num);
else if(2==type)//可乐常温
return new ChinaBeverage_2(num);
else
return null;
}
public Chicken createChicken(int type,int num)
{
if(1==type)//香辣鸡腿
return new ChinaChicken_1(num);
else if(2==type)//奥尔良鸡腿
return new ChinaChicken_2(num);
else
return null;
}
// 生产薯条
/*public FrenchFries createFrenchFries(int num)
{
return new ChinaFrenchFries(num);
}*/
public Hamburger createHamburger(int type,int num)
{
if(1==type)//香辣鸡腿堡
return new ChinaHamburger_1(num);
else if(2==type)//虾堡
return new ChinaHamburger_2(num);
else
return null;
}
//生产套餐
public Meal creatMeal(int type,int num){
if(1==type)//套餐A
return new ChinaMeal_1(num);
else if(2==type)//套餐B
return new ChinaMeal_2(num);
else
return null;
}
//生产薯条
public FrenchFries createFrenchFries(int type, int num) {
// TODO Auto-generated method stub
return new ChinaFrenchFries(num);
}
}
public class Menu {
public void Ham(){
System.out.println("--------------菜单--------------");
System.out.println("汉堡类");
System.out.println("1.香辣鸡腿堡-----------------9.0¥");
System.out.println("2.香辣虾堡------------------8.0¥");
System.out.println("鸡腿类");
System.out.println("1.香辣鸡腿------------------7.0¥");
System.out.println("2.奥尔良鸡腿-----------------6.0¥");
System.out.println("饮料类");
System.out.println("1.百事可乐(加冰)-------------5.0¥");
System.out.println("2.百事可乐(常温)-------------5.0¥");
System.out.println("薯条类");
System.out.println("1.薯条--------------------7.0¥");
System.out.println("套餐类");
System.out.println("套餐A:香辣鸡腿堡+薯条+可乐-------33.0¥");
System.out.println("套餐B:香辣虾堡+奥尔良鸡腿+可乐----30.0¥");
System.out.println("-------------------------------");
}
}
import java.util.Scanner;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.text.*;
public class Main {
static Factory kfc = new ProductFood();//定义一个接口类型的对象
static Customer customer = new Customer(kfc);//创建职员
static int order; //用户选的的菜系
static int type; //用户选择的食物
static int num; //数量
public static void main(String[] args)
{
Main.menu();//调用函数menu
}
public static void menu(){
try{
Calendar cal=Calendar.getInstance();
int y=cal.get(Calendar.YEAR); //获取系统当前时间的年份
int m=cal.get(Calendar.MONTH)+1; //获取系统当前时间的月份
int d=cal.get(Calendar.DATE);//获取系统当前时间的日期
FileWriter pw=new FileWriter("order.txt",true);//将数据保存到文件order中
BufferedWriter out=new BufferedWriter(pw);
out.write("* * * * * * * 欢迎来到肯德基 * * * * * * *");
out.newLine();
Menu menu=new Menu();
out.write("本店菜单如下:");
out.newLine();//换行输出
out.write("--------------------菜单--------------------");
out.newLine();
out.write("汉堡类");
out.newLine();
out.write("1.香辣鸡腿堡-------------------9.0¥");
out.newLine();
out.write("2.香辣虾堡---------------------8.0¥");
out.newLine();
out.write("鸡腿类");
out.newLine();
out.write("1.香辣鸡腿---------------------7.0¥");
out.newLine();
out.write("2.奥尔良鸡腿-------------------6.0¥");
out.newLine();
out.write("饮料类");
out.newLine();
out.write("1.百事可乐(加冰)--------------5.0¥");
out.newLine();
out.write("2.百事可乐(常温)--------------5.0¥");
out.newLine();
out.write("薯条类");
out.newLine();
out.write("1.薯条---------------------------7.0¥");
out.newLine();
out.write("套餐类");
out.newLine();
out.write("套餐A:香辣鸡腿堡+薯条+可乐------33.0¥");
out.newLine();
out.write("套餐B:香辣虾堡+奥尔良鸡腿+可乐--30.0¥");
out.newLine();
out.write("-----------------------------------------------");
out.newLine();
menu.Ham();//调用函数Ham,显示菜单
int flag=1;
double sum1=0;
double sum2=0;
double sum3=0;
double sum4=0;
double sum5=0;
double sum6=0;
double skr1;
while(flag!=0){
System.out.println("请输入餐类");
Scanner sc=new Scanner(System.in);
order=sc.nextInt();
System.out.println("请输入食物种类");
type=sc.nextInt();
System.out.println("请输入数量");
num=sc.nextInt();
switch(order){
case 1:
sum1=customer.orderHamburger(type, num);//点餐为汉堡类时,返回价格
//out.write(customer.orderHamburger(type, num));
break;
case 2:
sum2=customer.orderChicken(type, num);//点餐为鸡腿类时,返回价格
//out.write(customer.orderChicken(type, num));
break;
case 3:
sum3=customer.orderBeverage(type, num);//点餐为饮料类时,返回价格
//out.write(customer.orderFrenchFries(type, num));
break;
case 4:
sum4=customer.orderFrenchFries(type, num);//点餐为薯条类时,返回价格
break;
case 5:
sum5=customer.orderMeal(type, num);//点餐为套餐类时,返回价格
//out.write(customer.orderMeal(type, num));
break;
default:
System.out.println("对不起,没有该餐品");
}
//将小票写入文件中
switch (order) {
case 1:
out.write("本次餐类为\t\t"+"汉堡包");
out.newLine();
if(type==1)
out.write("---香辣鸡腿堡");
else
out.write("---香辣虾堡");
out.newLine();
out.write("数量为\t\t\t"+num);
break;
case 2:
out.write("本次餐类为\t\t\t"+"鸡腿" );
out.newLine();
if(type==1)
out.write("---香辣鸡腿");
else
out.write("---奥尔良鸡腿");
out.newLine();
out.write("数量为\t\t\t"+num);
break;
case 3:
out.write("本次餐类为\t\t\t"+"饮料" );
out.newLine();
if(type==1)
out.write("---可乐(加冰)");
else
out.write("---可乐(常温)");
out.newLine();
out.write("数量为\t\t\t"+num);
break;
case 4:
out.write("本次餐类为\t\t\t"+"薯条" );
out.newLine();
out.write("---薯条");
out.newLine();
out.write("数量为\t\t\t"+num);
break;
case 5:
out.write("本次餐类为\t\t\t"+"套餐" );
out.newLine();
if(type==1)
out.write("---套餐A");
else
out.write("---套餐B");
out.newLine();
out.write("数量为\t\t\t\t"+num);
break;
default: break;
}
out.newLine();
System.out.println("继续点餐:0---no 1---yes");//输入变量选择是否继续点餐
flag=sc.nextInt();
}
//skr.strategy();
double sum=sum1+sum2+sum3+sum4+sum5+sum6;//点餐总价
//判断日期是否是五月一日
if(m==5&&d==1){
System.out.println("今天是五一劳动节今天消费可打八折!");
System.out.println("共花费"+sum*0.8+"祝您用餐愉快");//打折优惠
}
else{
int tag;//客户是否有优惠券
System.out.println("您是否有优惠券");
System.out.println("0---NO 1---YES");
Scanner sc=new Scanner(System.in);
tag=sc.nextInt();
if(tag==1){
sum=sum*0.85;
System.out.println("本次用餐可以打八五折");
System.out.println("共计"+sum+"元");//输出总共费用
System.out.println("使用优惠券一张");
out.write("使用优惠券一张");
out.newLine();
}
else
{
System.out.println("共计"+sum+"元");//输出总共费用
}
out.write("总计"+sum+"元");
out.newLine();
out.write("祝你用餐愉快");
out.newLine();
//skr.strategy(sum);
//System.out.println("共需"+sum);
System.out.println("祝您用餐愉快!");
}
if(sum>100){
//System.out.println("总计"+sum);
System.out.println("本次点餐您可以获得本店八五折的优惠券,供你下次使用");
out.write("本次点餐您可以获得本店八五折的优惠券,供你下次使用");
out.newLine();
}
System.out.println(y+"年"+m+"月"+d+"日");
out.write(y+"年"+m+"月"+d+"日");//将年月日写入文件中
out.newLine();
out.close();
}catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.调试及运行截图
①调试截图
②运行结果
③小票截图(文件)
5.总结
①遇到的问题:这次的作业掌握面向对象程序设计的方法,在编写代码时没有思路因此上网学习了一下别人写的代码,了解到可以用两种模式来完成此次作业,一种是工厂方法模式,另外一种是抽象工厂模式。在创建工厂的过程中,因为对模式的不熟悉遇到很多问题,比如,使用方法重构在食物的基类里打印输出食物信息。在把小票写入文件的过程中,也遇到了一些问题,因为有些信息是要调用其他累里面的函数,但是用out.write()函数写入文件会出错,试了好多种方法都不可以,所以就参考了RPG角色生成器中的写入文件的方法,将信息一条一条的写入文件。活动时间是使用Calendar类来编写的,这样有便于后判断事假是否在活动范围之内,不过,最后的结果月份少一个月,就在month后面加了1。
②心得:本次作业是将上次的上机作业综合起来,对于我来说有些难度,不过通过参考网上的部分代码及相关知识,还是顺利的把基本要求完成了,提高要求现在实现不了,不过在后面的学习当中,会提高自己,继续完善该收银系统的功能。在本次的编写代码过程中,掌握了工厂方法模式及抽象工厂模式两种模式,并且对其他知识的运用更加熟练了,比如,了解获取系统当前时间的几种方式。