一些概念
# 策略模式
# 定义一系列算法,把它们一一封装起来,并且使他们可以相互替换,使得算法
# 可以独立于使用它的客户而变化。
# 模板方法
# 访问者模式
# 重构策略模式
# 代码:
# 经典的策略模式.py
# 使用函数实现策略模式.py
# 享元(flyweight)
# 是可共享的对象,可以同时在多个上下文中使用
# 命令模式 : 目的是解耦调用操作的对象(调用者)和提供实现的对象(接收者)
经典的策略模式:电商折扣.py
# 有1000或者以上积分 享受5%折扣
# 同一订单中单个商品数量达到20或者以上,享10%折扣
# 订单中的不同商品达到10个或以上,享7%折扣
# 一个订单只能享受一个折扣
"""上下文:
把计算委托给不同的算法可互换组件,本例为Order,它会根据不同的算法计算促销折扣
策略:
实现不同算法的共同接口,本例中Promotion这个抽象类扮演这个角色
具体策略:
策略的具体子类,fidelityPromo、BulkPromo\LargeOrderPromo是这里实现的三个具体策略"""
# 实现Order类,支持插入式折扣策略
from abc import ABC,abstractmethod
from collections import namedtuple
Customer = namedtuple('Customer','name fidelity') # 用命名元组保存客户信息 名字 忠诚度(积分)
class LineItem:
def __init__(self,product,quantity,price): # 商品\数量\价格
self.product = product
self.quantity = quantity
self.price = price
def total(self): # 计算金额
return self.price * self.quantity
class Order: # 上下文/订单
def __init__(self,customer,cart,promition = None): # 客户\购物车\促销折扣
self.customer = customer
self.cart = cart
self.promotion = promition
def total(self):
if not hasattr(self,'__total'):
self.__total = sum(item.total() for item in self.cart)
return self.__total
def due(self): # 应付款
if self.promotion is None:
discount = 0 # 折扣率
else:
discount = self.promotion.discount(self)
return self.total() - discount
def __repr__(self):
fmt = '<Order total:{:.2f} due:{:.2f}>'
return fmt.format(self.total(),self.due())
class Promotion: # 策略,抽象基类
@abstractmethod
def discount(self,order):
'''返回折扣金额(正值)'''
class FidelityPromo(Promotion): # 第一个具体策略
'''为积分1000及以上客户提供5%折扣'''
def discount(self,order):
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
class BuckItemPromo(Promotion):
'''单个商品数量20及以上提供10%的折扣'''
def discount(self,order):
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total()* .1
return discount
class LargeOrderPromo(Promotion):
'''不同商品达到10个或以上提供7%折扣'''
def discount(self,order):
distinct_items = {item.product for item in order.cart} # 去重
if len(distinct_items) >= 10:
return order.total()*.07
return 0
if __name__ == '__main__':
joe = Customer('John Doe',0)
ann = Customer('Ann Smith',1100)
cart = [LineItem('banana',4,.5),
LineItem('apple',10,1.5),
LineItem('watermellon',5,5.0)]
print(Order(joe, cart, FidelityPromo()))
print(Order(ann, cart, FidelityPromo()))
banana_cart = [LineItem('banana',30,.5),
LineItem('apple',10,1.5)]
print(Order(joe, banana_cart, BuckItemPromo()))
large_order = [LineItem(str(item_code),1,1.0)
for item_code in range(10)]
print(Order(joe, large_order, LargeOrderPromo()))
print(Order(joe, cart, LargeOrderPromo()))
使用函数实现策略模式.py
# 有1000或者以上积分 享受5%折扣
# 同一订单中单个商品数量达到20或者以上,享10%折扣
# 订单中的不同商品达到10个或以上,享7%折扣
# 一个订单只能享受一个折扣
"""上下文:
把计算委托给不同的算法可互换组件,本例为Order,它会根据不同的算法计算促销折扣
策略:
实现不同算法的共同接口,本例中Promotion这个抽象类扮演这个角色
具体策略:
策略的具体子类,fidelityPromo、BulkPromo\LargeOrderPromo是这里实现的三个具体策略"""
# 实现Order类,支持插入式折扣策略
from abc import ABC,abstractmethod
from collections import namedtuple
Customer = namedtuple('Customer','name fidelity') # 用命名元组保存客户信息 名字 忠诚度(积分)
class LineItem:
def __init__(self,product,quantity,price): # 商品\数量\价格
self.product = product
self.quantity = quantity
self.price = price
def total(self): # 计算金额
return self.price * self.quantity
class Order: # 上下文/订单
def __init__(self,customer,cart,promition = None): # 客户\购物车\促销折扣
self.customer = customer
self.cart = cart
self.promotion = promition
def total(self):
if not hasattr(self,'__total'):
self.__total = sum(item.total() for item in self.cart)
return self.__total
def due(self): # 应付款
if self.promotion is None:
discount = 0 # 折扣率
else:
discount = self.promotion.discount(self)
return self.total() - discount
def __repr__(self):
fmt = '<Order total:{:.2f} due:{:.2f}>'
return fmt.format(self.total(),self.due())
class Promotion: # 策略,抽象基类
@abstractmethod
def discount(self,order):
'''返回折扣金额(正值)'''
class FidelityPromo(Promotion): # 第一个具体策略
'''为积分1000及以上客户提供5%折扣'''
def discount(self,order):
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
class BuckItemPromo(Promotion):
'''单个商品数量20及以上提供10%的折扣'''
def discount(self,order):
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total()* .1
return discount
class LargeOrderPromo(Promotion):
'''不同商品达到10个或以上提供7%折扣'''
def discount(self,order):
distinct_items = {item.product for item in order.cart} # 去重
if len(distinct_items) >= 10:
return order.total()*.07
return 0
if __name__ == '__main__':
joe = Customer('John Doe',0)
ann = Customer('Ann Smith',1100)
cart = [LineItem('banana',4,.5),
LineItem('apple',10,1.5),
LineItem('watermellon',5,5.0)]
print(Order(joe, cart, FidelityPromo()))
print(Order(ann, cart, FidelityPromo()))
banana_cart = [LineItem('banana',30,.5),
LineItem('apple',10,1.5)]
print(Order(joe, banana_cart, BuckItemPromo()))
large_order = [LineItem(str(item_code),1,1.0)
for item_code in range(10)]
print(Order(joe, large_order, LargeOrderPromo()))
print(Order(joe, cart, LargeOrderPromo()))