一、题目分析
1.1、题目要求
正常餐品结算和找零。基本套餐结算和找零。使用优惠劵购买餐品结算和找零。可在一定时间段参与店内活动(自行设计或参考官网信息)。模拟打印小票的功能(写到文件中)。
基本要求:程序设计风格良好,控制台界面友好,最多两人一组完成任务。实现功能测试代码,确保程序的健壮性。画出使用的设计模式图。
1.2、算法实现
1.2.1、使用抽象工厂方法产生食物
肯德基生产食物,通过抽象方法工厂建立肯德基工厂,建立抽象食物类设置属性,建立食物接口,所有食物类的基类继承抽象食物基类,实现食物接口。
建立抽象工厂,包含各个食物的创建方法。具体的工厂是这个接口的子类,重写工厂的方法,创建具体食物对象。专门建立一个工厂类用来调用具体工厂中的产生具体食物对象的方法,通过反射,从客户端得知他们需要什么食物,从而生产什么食物。
1.2.2、使用策略模式实现结算功能
当付钱的时候可以根据策略的不同选择不同的付钱方式,可以选择支付宝,微信,零钱付款,各个付款方式优惠方式不同,这个可以通过策略模式实现。
二、关键算法构造 2.1、文档注释 2.1.1、食物基类
/*** 食物基类*/abstract class BaseFood {/*** 类别*/String name;/*** 数量*/int num;/*** 价格*/float price;/*** 合计* @return 食物总价格*/public float totalPrice() {return this.num * this.price;}}
2.1.2、抽象食物接口
/*** 抽象食物接口*/interface IFood {/*** 打印输出食物信息*/void printMessage();}
2.1.3、抽象肯德基工厂
/*** 建立工厂* 创建抽象肯德基工厂* 生产抽象食物*/interface IKfcFactory {/*** 生产帕尼尼* @param num 要买的数量* @return BaseHamburg对象*/BaseHamburg createPaNiNiHamburg(int num);/*** 生产劲脆鸡腿堡* @param num 要买的数量* @return BaseHamburg对象*/BaseHamburg createCrispyChickenHamburg(int num);/*** 生产巧克力华夫* @param num 要买的数量* @return BaseFrenchFries对象*/BaseSweetmeats createChocolateWaffleSweetmeats(int num);/*** 生产生产香香红豆派* @param num* @return*/BaseSweetmeats createRedBeanPieSweetmeats(int num);/*** 生产热辣薯片鸡翅* @param num 要买的数量* @return BaseChicken对象*/BaseChicken createHotPotatoChipsChickenWings(int num);/*** 生产劲爆香辣鸡翅* @param num 要买的数量* @return BaseChicken对象*/BaseChicken createPiquancyChickenWings(int num);/*** 生产百事可乐* @param num 要买的数量* @return BaseBeverage对象*/BaseBeverage createBaiShiKolaBeverage(int num);/*** 生产咖啡* @param num 要买的数量* @return BaseBeverage对象*/BaseBeverage createCoffeeBeverage(int num);/*** 生产翅桶嫩牛五方套餐* @param num 要买的数量* @return BaseSetMeal对象*/BaseSetMeal createWingBucketTenderFiveSides(int num);/*** 生产辣鸭肉卷人气明星套餐* @param num 要买的数量* @return BaseSetMeal对象*/BaseSetMeal createSpicyDuckRollPopularStarMealBase(int num);}
2.2、类图设计
kfc抽象工厂设计模式类图(图片分辨率较高,请放大查看),如果实在看不清,请查看下面链接source文件夹下的图片
三、程序实现
参考以下文件
链接
四、调试、测试及运行结果
4.1调试截图
菜单显示
当选择1号餐数量为2时
food为抽象出来的工厂通过餐品选择调用相应的创建创建方法
shouldPayMoney为应该付的钱
继续选择食物5号食物数量6个
baseFood为ArrayList数组用来存放选择的餐品,刚才选了芝士帕尼尼和百事可乐,所以存储的是相应的食物
输入界面
cutDown为优惠券的价格
giveMoney为客户给的钱
change为找零
shouldPayMoney为应该付的钱
选择支付宝支付有5元的红包,找零界面
4.2测试截图
点餐根据菜单点餐,提供友好的输入检查,知道输入正确为止
选择数量检查,直到输入正确为止
输入优惠券界面,进行输入检查
选择支付方式,选择微信支付,享受95折优惠
打印小票
五、经验归纳
第一次接触抽象工厂模式,通过反射的方式获得真正的实例化对象。只会一种方式:专门设计一个类用来实例化其他类的对象,其他类往往有公共的父类,即Food接口,这样使用反射的机制就很好实现,直接通过参数就能够实例化相应的对象。一开始只知道通过接口实现公共的父类,但真正的做的时候,发现每一个食物都有相同的属性要设置,所以要设计一个公共的抽象父类来实现,这样才能赋予每一个子类相关属性。
同时熟练掌握了处理多个食物产品蔟的构建方法,深深感受到了抽象工厂方法模式的优点,和抽象工厂方法比较一下抽象工厂模式进一步扩展了工厂方法模式,它把原先的工厂方法模式中只能有一个抽象产品不能添加产品族的缺点克服了,抽象工厂模式不仅仅遵循了OCP原则,而且可以添加更多产品(抽象产品),具体工厂也不仅仅可以生成单一产品,而是生成一组产品,抽象工厂也是声明一组产品,对应扩展更加灵活,但是要是扩展族系就会很笨重。 所以就选择了抽象工厂模式。
在付钱的时候,使用了策略模式,通过不同的策略选择不同的付款方式,使用策略模式支持开闭原则(OCP)、策略模式使用继承模式抽取公共代码到基类,避免重复代码、策略模式避免使用多重条件判断语句 (if/else、switch 等)。方便了对付款方式的选择。
遗憾的是没有实现提高要求的可视化功能和数据库存储,但是后期学习一定将程序完善。