一、题目分析
同学们应该都去麦当劳或肯德基吃过快餐吧?请同学们参考肯德基官网的信息模拟肯德基快餐店的收银系统,并合理使用C++或Java或Python,结合设计模式(2种以上),至少实现系统的以下功能:
1.正常餐品结算和找零。
2.基本套餐结算和找零。
3.使用优惠劵购买餐品结算和找零。
4.可在一定时间段参与店内活动(自行设计或参考官网信息)。
5.模拟打印小票的功能(写到文件中)。
基本要求:
1.程序设计风格良好,控制台界面友好,最多两人一组完成任务。
2.实现功能测试代码,确保程序的健壮性。
3.画出使用的设计模式图。
提高要求:
1.实现可视化界面(使用MFC)。
2.实现会员储值卡功能,完成储值卡消费。
3.实现当天营业额和餐品销量计算和统计,用数据库记录。
二 、算法构造
UML图:
三、算法实现
程序源代码如下:
// 抽象类AbstractBaseFood
package xtx.factory.custom;
public class AbstractBaseFood {
protected String kind; // 类别
protected int num; // 数量
protected float price; // 价格
public float totalPrice() //找零 // 合计
{
return this.num * this.price;
}
}
//Food接口实现各类食物信息的打印
package xtx.factory.custom;
public interface Food {
/** * 打印输出食物信息 * @return */
String printMesage();
}
//各类果汁的基类Beverage
package xtx.factory.custom;
public abstract class Beverage extends AbstractBaseFood implements Food {
public String printMesage() {
return ("--" + this.kind + "饮料,\t单价:" + this.price + ",\t数量:" + this.num + ",\t合计:" + this.totalPrice());
}
}
//各类鸡翅的基类ChickenWings
package xtx.factory.custom;
public abstract class ChickenWings extends AbstractBaseFood implements Food {
public String printMesage() {
return ("--" + this.kind + "鸡翅,\t单价:" + this.price + ",\t数量:" + this.num + ",\t合计:" + this.totalPrice());
}
}
//各类薯条的基类FrenchFries
package xtx.factory.custom;
public abstract class FrenchFries extends AbstractBaseFood implements Food {
public String printMesage() {
return ("--" + this.kind + "薯条,\t单价:" + this.price + ",\t数量:" + this.num + ",\t合计:" + this.totalPrice());
}
}
//各类果汁的基类Hamburg
package xtx.factory.custom;
public abstract class Hamburg extends AbstractBaseFood implements Food {
public String printMesage() {
return ("--" + this.kind + "汉堡,\t单价:" + this.price + ",\t数量:" + this.num + ",\t合计:" + this.totalPrice());
}
}
//建立Beverage的具体实现类ChinaBeverage
package xtx.factory.custom;
public class ChinaBeverage extends Beverage {
public ChinaBeverage(int num) {
this.kind = "可乐";
this.price = 6.0f;
this.num = num;
}
}
//建立ChickenWings的具体实现类ChinaChickenWings
package xtx.factory.custom;
public class ChinaChickenWings extends ChickenWings {
public ChinaChickenWings(int num) {
this.kind = "奥尔良烤鸡翅";
this.price = 2.5f;
this.num = num;
}
}
//建立FrenchFries的具体实现类ChinaFrenchFries
package xtx.factory.custom;
public class ChinaFrenchFries extends FrenchFries {
public ChinaFrenchFries(int num) {
this.kind = "普通风味薯条";
this.price = 8.0f;
this.num = num;
}
}
//建立Hamburg的具体实现类ChinaHamburg
package xtx.factory.custom;
public class ChinaHamburg extends Hamburg {
public ChinaHamburg(int num) {
this.kind = "麻辣风味汉堡";
this.price = 6.0f;
this.num = num;
}
}
//具体KFC工厂类
package xtx.factory.custom;
public class ChinaKfcFactory implements KfcFactory {
// 生产可乐
public ChinaBeverage createBeverage(int num) {
return new ChinaBeverage(num);
}
// 生产奥尔良烤鸡翅
public ChinaChickenWings createChickenWings(int num) {
return new ChinaChickenWings(num);
}
// 生产薯条
public ChinaFrenchFries createFrenchFries(int num) {
return new ChinaFrenchFries(num);
}
// 生产麻辣风味鸡腿汉堡
public ChinaHamburg createHamburg(int num) {
return new ChinaHamburg(num);
}
}
//抽象工厂KfcFactory
package xtx.factory.custom;
public interface KfcFactory {
// 生产汉堡
public ChinaHamburg createHamburg(int num);
// 生产薯条
//public xtx.FrenchFries createFrenchFries(int num);
public FrenchFries createFrenchFries(int num);
// 生产鸡翅
public ChinaChickenWings createChickenWings(int num);
// 生产饮料
public ChinaBeverage createBeverage(int num);
}
//建立Customer类实现食物的选择和文件存储:
package xtx.factory.custom;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Customer {
// 抽象工厂
private KfcFactory kfcFactory;
// 构造方法将抽象工厂作为参数传入
public Customer(KfcFactory kfcFactory2) {
this.kfcFactory = kfcFactory2;
}
/** * 订购食物 * @throws IOException */
private String s[] =new String[5];
@SuppressWarnings("resource")
public void showbill() throws IOException {
BufferedWriter bw=new BufferedWriter(new FileWriter("E://eclipse_workspace//xtx.factory.custom//src//xtx//factory//custom//show.txt",true));
bw.write("---------------------账单如下---------------------");
bw.newLine();
for(int i=0;i<5;i++) {
bw.write(s[i]);
bw.newLine();
bw.flush();
}
}
// 订购麻辣鸡腿汉堡
public float orderHamburg(int num) throws IOException {
// 获得麻辣鸡腿汉堡
ChinaHamburg hamburg = kfcFactory.createHamburg(num);
// 输出订购信息
System.out.print(hamburg.printMesage());
s[0]=hamburg.printMesage();
System.out.print("\n");
// 返回总价
return hamburg.totalPrice();
}
// 订购奥尔良烤鸡翅
public float orderChickenWings(int num)
{
// 获得奥尔良烤鸡翅
ChinaChickenWings chickenWings = kfcFactory.createChickenWings(num);
// 输出订购信息
System.out.print(chickenWings.printMesage());
s[1]=chickenWings.printMesage();
System.out.print("\n");
// 返回总价
return chickenWings.totalPrice();
}
// 订购薯条
public float orderFrenchFries(int num) {
// 获得薯条
ChinaFrenchFries frenchFries = (ChinaFrenchFries) ((KfcFactory) kfcFactory).createFrenchFries(num);
// 输出订购信息
System.out.print(frenchFries.printMesage());
s[2]=frenchFries.printMesage();
System.out.print("\n");
// 返回总价
return frenchFries.totalPrice();
}
// 订购可乐
public float orderBeverage(int num) {
// 获得可乐
ChinaBeverage beverage = kfcFactory.createBeverage(num);
// 输出订购信息
System.out.print(beverage.printMesage());
s[3]=beverage.printMesage();
System.out.print("\n");
return beverage.totalPrice();
}
//订购套餐一
public float ordercombo1(int num) {
// 获得可乐
ChinaBeverage beverage = kfcFactory.createBeverage(num);
// 获得麻辣鸡腿汉堡
ChinaHamburg hamburg = kfcFactory.createHamburg(num);
s[4]=("--套餐一,\t单价:21,\t数量:"+num+"\t\t合计:"+(beverage.totalPrice()+hamburg.totalPrice())+"\n");
System.out.print("--套餐一,\t单价:21,\t数量:"+num+"\t\t合计:"+(beverage.totalPrice()+hamburg.totalPrice())+"\n");
return beverage.totalPrice()+hamburg.totalPrice();
}
}
//MainApp
package xtx.factory.custom;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class MainApp {
/** * 主应用程序方法 * * @param args * @throws IOException
* @throws IOException */
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
/** * 定义一个肯德基(IKfcFactory类型) */
KfcFactory kfcFactory = (KfcFactory) new ChinaKfcFactory();
Customer customer = new Customer(kfcFactory);
/** * 开始点餐 */
// 一个麻辣鸡腿汉堡
Scanner in =new Scanner(System.in);
//System.out.print("请输入付款金额");
System.out.print("-----现有如下产品-----\n");
System.out.print("--麻辣风味汉堡\t单价:15.0.\n--奥尔良风味鸡翅\t单价:3.0\n--普通风味薯条\t单价:8.0\n--可乐饮料\t单价:6.0\n--套餐一(麻辣风味汉堡+可乐饮料)\t单价:21\n");
System.out.print("\n-----------------------");
System.out.print("\n请点餐:\n");
System.out.print("请输入麻辣风味汉堡数量---:");
int a1=in.nextInt();
System.out.print("请输入奥尔良风味鸡翅数量-:");
int a2=in.nextInt();
System.out.print("普通入风味薯条数量------:");
int a3=in.nextInt();
System.out.print("请输入可乐饮料数量------:");
int a4=in.nextInt();
System.out.print("请输入套餐份数---------:");
int a5=in.nextInt();
System.out.print("\n------账单如下-----\n");
float hamhurgMoney = customer.orderHamburg(a1);
// 四个奥尔良烤鸡翅
float chickenWingsMoney = customer.orderChickenWings(a2);
// 一包薯条
float frenchFriesMoney = customer.orderFrenchFries(a3);
// 两杯可乐
float beverageMoney = customer.orderBeverage(a4);
float combo1=customer.ordercombo1(a5);
//
float sum=hamhurgMoney + chickenWingsMoney + frenchFriesMoney + beverageMoney+combo1;
customer.showbill();
System.out.println("总计:" + (sum));
System.out.print("请输入付款金额:");
int a=in.nextInt();
System.out.print("找零:"+(a-sum));
customer.showbill();
BufferedWriter bw=new BufferedWriter(new FileWriter("E://eclipse_workspace//xtx.factory.custom//src//xtx//factory//custom//show.txt",true));
bw.write("总计: "+sum);
bw.newLine();
bw.write("付款:"+a);
bw.newLine();
float y=a-sum;
bw.write("找零:"+y);
bw.newLine();
bw.flush();
bw.close();
}
}
四、调试、测试及运行结果
1、程序调试
2、总测试结果
五.经验归纳
1、思路:
第一步,通过参考肯德基官网收银系统,知道需要以下几方面的程序:(1)肯德基工厂——生产食物的工厂;
(2)食物(汉堡、鸡翅、薯条、可乐等等);
(3)工厂生产的产品;
(4)顾客——点餐;
(5)用户——使用点餐系统为顾客点餐及结账;
第二步,具体实现:使用工厂方法模式和抽象工厂模式两种设计模式,并应用了“开闭”原则和“依赖倒置”原则。
(1)肯德基店就是一个具体的工厂,运用工厂方法模式
我们需要抽象一个工厂,在抽象工厂中指明了生产各种抽象食物的方法,如生产汉堡、鸡翅、薯条、饮料等。KfcFactory来实现这个抽象工厂,生产具体的食品,如生产麻辣风味鸡腿汉堡、奥尔良烤鸡翅、普通风味薯条、可乐等。
(2)我们还需要对每个具体的食物添加抽象父类,如饮料就是抽象父类,可乐就是饮料的一个子类。依次类推,我们会发现,每一种食物又都存在着一些共同的属性,如数量(num)、种类(kind)、价格(price)等,因此,我们继续进行抽象,所有的抽象食物都继承一个抽象父类。
(3)订餐时,不再使用工厂方法模式,而是使用组合的方式,将抽象工厂作为顾客类中的一个实例变量,顾客需要任何产品的时候,只需要向工厂请求即可,这就是抽象工厂模式的应用方式。顾客类和工厂类分开,客户无须修改就可以获得新产品。
第三步,编写程序并修正错误,完成报告。
2、知识
抽象工厂模式的设计原则:
1.多用对象组合,少用继承;
2.针对抽象编程,不针对实现编程;
3.产品对象通过工厂暴露的方法创建。
抽象工厂模式的使用场合:
1.创建产品家族,相关产品集合在一起使用的时候;
2.想要提供一个产品类库,并只想显示其接口而不是实现时;
3.通过组合的方式使用工厂时。
附:作业参考:https://www.jb51.net/article/140406.htm