Created
January 15, 2018 06:11
-
-
Save nlpjoe/7f96aeda930f0f7e88e90190d3106b2a to your computer and use it in GitHub Desktop.
[策略设计模式]折扣方案的策略设计模式#python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 6.使用一等函数实现设计模式 | |
from collections import namedtuple | |
Customer = namedtuple('Customer', 'name fidelity') | |
class LineItem(object): | |
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(object): #上下文 | |
def __init__(self, customer, cart, promotion=None): | |
self.customer = customer | |
self.cart = list(cart) | |
self.promotion = promotion | |
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(self) # 调用策略得到打折值 | |
return self.total() - discount | |
def __repr__(self): | |
fmt = '<Order total:{:.2f} due:{:.2f}>' | |
return fmt.format(self.total(), self.due()) | |
def fidelity_promo(order): | |
"""积分1000->5%折扣""" | |
return order.total() * .05 if order.customer.fidelity >= 1000 else 0 | |
def bulk_item_promo(order): | |
"""单个商品为20个或以上时提供10%折扣""" | |
discount = 0 | |
for item in order.cart: | |
if item.quantity >= 20: | |
discount += item.total() * .1 | |
return discount | |
def large_order_promo(order): | |
"""不同商品达到10个 7%折扣""" | |
distinct_items = {item.product for item in order.cart} | |
if len(distinct_items) >= 10: | |
return order.total() * .07 | |
return 0 | |
def best_promo(order): | |
promos = [fidelity_promo, bulk_item_promo, large_order_promo] # 罗列所有策略 | |
promos = [globals()[name] for name in globals() # 通过内省模块找到所有策略函数 | |
if name.endswith('_promo') and name != 'best_promo'] | |
print(promos) | |
return max(promo(order) for promo in promos) | |
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)] | |
banana_cart = [LineItem('banana', 30, .5), | |
LineItem('apple', 10, 1.5)] | |
long_order = [LineItem(str(item_code), 1, 1.0) | |
for item_code in range(10)] | |
Order(joe, banana_cart, best_promo) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment