from abc import ABC,abstractmethod
from collections import namedtuple
##############商品类##############
class Item:
def __init__(self,name,price,num):
self.name = name
self.price = price
self.num = num
def total(self):
return self.price * self.num
############订单类###############
class Order:
def __init__(self,customer,promotion=None):
self.cart = []
self.customer = customer
self.promotion = promotion
def add_to_cart(self,*items):
for item in items:
self.cart.append(item)
def total(self):
total = 0
for item in self.cart:
total += item.total()
return total
def due(self):
if not self.promotion:
discount = 0
else:
discount = self.promotion.discount(self)
return (self.total()-discount)
#################折扣策略类###################
class Promotion(ABC):
@abstractmethod
def discount(self,order):
pass
class FidelityPromo(Promotion):
"""
如果积分满100分,就可以兑换10元现金券
"""
def discount(self,order):
return 10 if order.customer.fidelity > 1000 else 0
class BulkItemPromo(Promotion):
"""
如果单件商品购买10件,即可9折
"""
def discount(self,order):
discount = 0
for item in order.cart:
if item.num >=10:
discount += item.total() * 0.1
return discount
class LargeOrderPromo(Promotion):
"""
如果订单总金额大于等于500,就减50
"""
def discount(self,order):
discount = 0
if order.total()>=500:
discount = 50
return discount
###############最优策略类#############
class BestPromo(Promotion):
def discount(self, order):
# 找出当前文件中所有的策略
all_promotion = [globals()[name] for name in globals() if name.endswith('Promo') and name != 'BestPromo']
# 计算最大折扣
return max([promo().discount(order) for promo in all_promotion])
#############消费者############
Customer = namedtuple('Customer','name fidelity')
if __name__ == '__main__':
xm = Customer('xiaoming',1500)
item1 = Item('鞋',200,3)
item2 = Item('衣服',400,1)
order = Order(xm,FidelityPromo())
order.add_to_cart(item1,item2)
# print(order.total())
# print(order.due())
xh = Customer('xiaohong',300)
item3 = Item('盐',10,10)
item4 = Item('油',50,10)
item5 = Item('米',70,2)
order = Order(xh,BestPromo())
order.add_to_cart(item3,item4,item5)
print(order.total())
print(order.due())