Created
January 15, 2018 06:50
-
-
Save nlpjoe/9f79b766d354142e61ebab755f3fb952 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
# 7 函数装饰器和闭包 | |
## 使用装饰器改进策略模式 | |
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()) | |
promos = [] | |
def promotion(promo_func): | |
promos.append(promo_func) | |
return promo_func | |
@promotion | |
def fidelity_promo(order): | |
"""积分1000->5%折扣""" | |
return order.total() * .05 if order.customer.fidelity >= 1000 else 0 | |
@promotion | |
def bulk_item_promo(order): | |
"""单个商品为20个或以上时提供10%折扣""" | |
discount = 0 | |
for item in order.cart: | |
if item.quantity >= 20: | |
discount += item.total() * .1 | |
return discount | |
@promotion | |
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): | |
return max(promo(order) for promo in promos) | |
def test(): | |
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)] | |
print(Order(joe, banana_cart, best_promo)) | |
test() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment