前言
本文为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):
pass
def accept_cash(self,money):
pass
# 正常收费
class CashNormal(CashSuper):
def accept_cash(self,money):
return money
# 打折收费
class CashRebate(CashSuper):
__moneyRebate = 1
def cash_rebate(self,moneyRebateStr):
self.__moneyRebate = float(moneyRebateStr)
def accept_cash(self,money):
return money*self.__moneyRebate
# 返利收费
class CashReturn(CashSuper):
__moneyCondition = 0
__moneyReturn = 0
def cash_return(self,moneyConditionStr,moneyReturnStr):
self.__moneyCondition = float(moneyConditionStr)
self.__moneyReturn = float(moneyReturnStr)
def accept_cash(self,money):
result = money
if (money >= self.__moneyCondition):
result = money - money // self.__moneyCondition * self.__moneyReturn
return result
# 产品的抽象类
class ProductFactory(object):
def __init__(self,name,price):
self.__product_name = name
self.__product_price = price
def set_product_name(self,name):
self.__product_name = name
def get_product_name(self):
return self.__product_name
def set_product_price(self,price):
self.__product_price = price
def get_product_price(self):
return self.__product_price
def get_cash(self):
pass
class 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 = 0
root = 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 = 0
self.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 + totalPrice
self.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()
最终效果: