前言
本文为datawhale2022年12月组队学习《大话设计模式》task4打卡学习,本次完成homework1。
【教程地址】https://github.com/datawhalechina/sweetalk-design-pattern
一、任务描述
1.1 背景
小李已经是一个工作一年的初级工程师了,他所在的公司是一家大型购物商场。随着各种网络购物软件兴起,老板也想做一个商场的购物 APP。分给小李的是一个一个订单结算模块,需要支持各种不同的结算策略。
1.2 需求
请帮小李写一个订单结算模块,要求支持多种结算策略:
- 原价
- 打 X 折
- 满减,满 X 元减 Y 元
请注意,商品有多种类型,每种类型可能会参与不同的活动,自然需要支持不同的结算策略。
1.3 任务
共三个小任务:
- Q1:方案设计。
- Q2:代码实现及结果截图。
- Q3:解释为什么要用这些模式。
1.4 要求
要求如下:
- 输入是一揽子商品,输出是最后的订单金额。
- 至少包含两种商品,每种使用不同的结算策略,策略可任选其中一个或两个组合(比如满减 + 打折)。
- 不要实现具体函数或方法的逻辑,可以使用
print
输出功能。
二、任务分析
根据要求,应该采用工厂方法模式以及策略模式。具体工作如下:
- 首先创建抽象的费用类
CashSuper
和产品工厂类ProductFactory
,用来分别代表不同收费策略类公共接口和具体产品的公共接口; - 分别创建收费策略类
CashNormal
、CashRebate
和CashReturn
,继承CashSuper
,用来实现相应的收费策略; - 再分别创建具体产品类
NormalProductFactory
、RebateProductFactory
和ReturnProductFactory
,继承于抽象类ProductFactory
,在三个类中各自定义创建对应具体产品实例的方法; - 创建策略模式上下文类
CashContext
,前端界面通过选择不同的销售策略,从而创建不同具体产品类的实例。
三、代码实现
整体上参考了策略模式案例的代码,自己在上面有所修改:
# -*- coding:utf-8 -*-
'''
@File : StrategyCash.py
@Time : 2022/12/21 10:58:24
@Author : ziyuan
@Version : 1.0
@Contact : 1104009634@qq.com
@Desc : 任务01订单结算模块策略模式实现
'''# here put the import lib
import tkinter
import tkinter.ttk# 收费的接口类
class CashSuper(object):def __init__(self):passdef accept_cash(self,money):pass# 正常收费
class CashNormal(CashSuper):def accept_cash(self,money):return money# 打折收费
class CashRebate(CashSuper):__moneyRebate = 1def cash_rebate(self,moneyRebateStr):self.__moneyRebate = float(moneyRebateStr)def accept_cash(self,money):return money*self.__moneyRebate# 返利收费
class CashReturn(CashSuper):__moneyCondition = 0__moneyReturn = 0def cash_return(self,moneyConditionStr,moneyReturnStr):self.__moneyCondition = float(moneyConditionStr)self.__moneyReturn = float(moneyReturnStr)def accept_cash(self,money):result = moneyif (money >= self.__moneyCondition):result = money - money // self.__moneyCondition * self.__moneyReturnreturn result# 产品的抽象类
class ProductFactory(object):def __init__(self,name,price):self.__product_name = nameself.__product_price = pricedef set_product_name(self,name):self.__product_name = namedef get_product_name(self):return self.__product_namedef set_product_price(self,price):self.__product_price = pricedef get_product_price(self):return self.__product_pricedef get_cash(self):passclass NormalProductFactory(ProductFactory):def __init__(self,name,price):super().__init__(name,price)self.cs = CashNormal()def get_cash(self):return self.cs.accept_cash(self.get_product_price())class RebateProductFactory(ProductFactory):def __init__(self,name,price):super().__init__(name,price)self.cs = CashRebate()self.cs.cash_rebate("0.8")def get_cash(self):return self.cs.accept_cash(self.get_product_price())class ReturnProductFactory(ProductFactory):def __init__(self,name,price):super().__init__(name,price)self.cs = CashReturn()self.cs.cash_return("300","100")def get_cash(self):return self.cs.accept_cash(self.get_product_price())# 策略模式上下文类实现
class CashContext(object):def __init__(self,typ,name,price):if typ == "正常收费":self.product = NormalProductFactory(name,price)elif typ == "打8折":self.product = RebateProductFactory(name,price)elif typ == "满300返100":self.product = ReturnProductFactory(name,price)def get_result(self):return self.product.get_cash()# 前端
class CashWindow(object):def __init__(self):self.total = 0root = tkinter.Tk()self.label1 = tkinter.Label(root,text="商品名称:")self.txtName = tkinter.Entry(root,width = 24,)self.label2 = tkinter.Label(root,text="商品价格:")self.txtPrice = tkinter.Entry(root,width = 24,)self.ibxList = tkinter.Text(root,width = 45, height = 10)self.label4 = tkinter.Label(root,text="总计:")self.iblResult = tkinter.StringVar()self.iblResult.set("%.2f"%self.total)self.result = tkinter.Label(root,textvariable=self.iblResult, height = 2, font = ('TimeNewsRoman',24))self.button = tkinter.Button(root,text="确定",width = 10,command = self.btnOk_click)self.buttonReset = tkinter.Button(root,text="重置",width = 10,command = self.btnReset_click)self.label3 = tkinter.Label(root,text="计算方式:")self.comboVar = tkinter.StringVar()self.combobox = tkinter.ttk.Combobox(root, textvariable = self.comboVar,width = 22,)self.combobox['value'] = ("正常收费","打8折","满300返100")self.combobox.current(0)self.layout()root.mainloop()def refresh(self):self.txtName.delete('0','end')self.txtPrice.delete('0','end')def layout(self):self.label1.grid(row = 0, column = 0, padx = (10,0), pady = 10)self.txtName.grid(row = 0, column = 1, pady = 10,padx = (0,5),)self.label2.grid(row = 1, column = 0, padx = (10,0))self.txtPrice.grid(row = 1, column = 1,padx = (0,5),)self.label3.grid(row = 2, column = 0, padx = (10,0))self.combobox.grid(row = 2, column = 1,padx = (0,5),pady = 10)self.ibxList.grid(row = 4, column = 0,columnspan = 4,padx = (5,5),pady = 10)self.label4.grid(row = 5, column = 0, padx = (10,0))self.result.grid(row = 5, column = 1,columnspan = 3, rowspan = 2)self.button.grid(row = 0, column = 2, columnspan = 2,pady = 10, padx = (0,10))self.buttonReset.grid(row = 1, column = 2, columnspan = 2, padx = (0,10))def btnReset_click(self):self.total = 0self.ibxList.delete('1.0','end')self.iblResult.set("%.2f"%self.total)self.refresh()# 主要部分def btnOk_click(self):csuper = CashContext(self.comboVar.get(),self.txtName.get(),float(self.txtPrice.get()))totalPrice = float(csuper.get_result())self.total = self.total + totalPriceself.ibxList.insert('end',"商品名称:"+self.txtName.get()+",商品价格:" +self.txtPrice.get()+",销售策略:"+self.comboVar.get()+"。合计:%.2f"%(totalPrice)+"\n")self.iblResult.set("%.2f"%self.total)self.refresh()if __name__ == '__main__':CashWindow()
最终效果: