6. Design Patterns with First-Class Functions
1. Refactoring Strategy
1.1 Classic Strategy

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, promotion=None):
self.customer = customer # 用户名
self.cart = list(cart) # 商品列表
self.promotion = promotion # obj
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(ABC): # an abstract base class
@abstractmethod
def discount(self, order): # 返回折扣的总钱数
pass class FidelityPromo(Promotion):
"""5% discount for customers with 1000 or more fidelity points"""
def discount(self, order):
return order.total() * .05 if order.customer.fidelity >= 1000 else 0 class BulkItemPromo(Promotion):
"""10% discount for each LineItem with 20 or more units"""
def discount(self, order):
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total() * .1
return discount class LargeOrderPromo(Promotion):
"""7% discount for orders with 10 or more distinct items"""
def discount(self, order):
distinct_items = {item.product for item in order.cart}
if len(distinct_items) >= 10:
return order.total() * .07
return 0 joe = Customer('John Doe', 1000)
cart = [LineItem('banana', 4, .5), LineItem('apple', 25, 1.5), LineItem('watermellon', 5, 5.0)]
print(Order(joe, cart, FidelityPromo())) # <Order total: 64.50 due: 61.27>
print(Order(joe, cart, BulkItemPromo())) # <Order total: 64.50 due: 60.75>
print(Order(joe, cart, LargeOrderPromo())) # <Order total: 64.50 due: 64.50>
1.2 Function-Oriented Strategy
- A flyweight is a shared object that can be used in multiple contexts simultaneously. (享元)
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, promotion=None):
self.customer = customer # 用户名
self.cart = list(cart) # 商品列表
self.promotion = promotion # obj
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): # created just once
"""5% discount for customers with 1000 or more fidelity points"""
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
def bulk_item_promo(order):
"""10% discount for each LineItem with 20 or more units"""
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total() * .1
return discount
def large_order_promo(order):
"""7% discount for orders with 10 or more distinct items"""
distinct_items = {item.product for item in order.cart}
if len(distinct_items) >= 10:
return order.total() * .07
return 0
joe = Customer('John Doe', 1000)
cart = [LineItem('banana', 4, .5), LineItem('apple', 25, 1.5), LineItem('watermellon', 5, 5.0)]
print(Order(joe, cart, fidelity_promo)) # <Order total: 64.50 due: 61.27>
print(Order(joe, cart, bulk_item_promo)) # <Order total: 64.50 due: 60.75>
print(Order(joe, cart, large_order_promo)) # <Order total: 64.50 due: 64.50>
1.3 Choosing the Best Strategy
promos = [fidelity_promo, bulk_item_promo, large_order_promo]
# promos = [globals()[name] for name in globals() if name.endswith('_promo') and name != 'best_promo']
# import inspect
# promos = [func for name, func in inspect.getmembers(promotions, inspect.isfunction)] # promotions为自定模块
def best_promo(order):
"""Select best discount available"""
return max(promo(order) for promo in promos)
promos = []
def promotion(promo_func):
promos.append(promo_func)
return promo_func @promotion
def fidelity_promo(order): # created just once
"""5% discount for customers with 1000 or more fidelity points"""
return order.total() * .05 if order.customer.fidelity >= 1000 else 0 @promotion
def bulk_item_promo(order):
"""10% discount for each LineItem with 20 or more units"""
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total() * .1
return discount @promotion
def large_order_promo(order):
"""7% discount for orders with 10 or more distinct items"""
distinct_items = {item.product for item in order.cart}
if len(distinct_items) >= 10:
return order.total() * .07
return 0
2. Command

6. Design Patterns with First-Class Functions的更多相关文章
- Learning JavaScript Design Patterns The Module Pattern
The Module Pattern Modules Modules are an integral piece of any robust application's architecture an ...
- Design Patterns Example Code (in C++)
Overview Design patterns are ways to reuse design solutions that other software developers have crea ...
- Massive Collection Of Design Patterns, Frameworks, Components, And Language Features For Delphi
Developer beNative over on GitHub has a project called Concepts which is a massive collection of Del ...
- Design Patterns Simplified - Part 3 (Simple Factory)【设计模式简述--第三部分(简单工厂)】
原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part3-factory/ Design ...
- Design Patterns Simplified - Part 2 (Singleton)【设计模式简述--第二部分(单例模式)】
原文链接: http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part-2-singleton/ De ...
- Head First Design Patterns
From Head First Design Patterns. Design Principle: Idnetify the aspects of your application that var ...
- Apex Design Patterns
Apex allows you to build just about any custom solution on the Force.com platform. But what are the ...
- [Design Patterns] 4. Creation Pattern
设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结,使用设计模式的目的是提高代码的可重用性,让代码更容易被他人理解,并保证代码可靠性.它是代码编制真正实现工程化. 四个关键元素 ...
- [Design Patterns] 3. Software Pattern Overview
When you're on the way which is unknown and dangerous, just follow your mind and steer the boat. 软件模 ...
- [Design Patterns] 1. Primary concept & term - UML
It's time to review design patterns, especially when I reach the turning-point of my career. That's ...
随机推荐
- 相机用的 SD Card 锁Lock 烂掉了,无法正常写入
没错,又碰到奇奇怪怪的SD Card Lock 烂掉了 , 无法正常写入,不要急,千万不要扔了,拿起透明胶粘在 Lock 处,注意不要粘住金手指哦,再放回去就可以读写了,但是透明胶不耐摩擦,用了几次 ...
- web框架学习路线
0.配置 1.路由 2.view 3.model 4.序列化与反序列化. 5.auth&permission 6.header处理 7.http client
- pytest.mark.parametrize()参数化的应用一
from page.LoginPage import Loginpage import os, sys, pytest base_dir = os.path.dirname(os.path.dirna ...
- Java High Level REST Client 之 创建索引
1. 创建索引请求 CreateIndexRequest request = new CreateIndexRequest("twitter"); 2.设置 2.1 分别设置 2. ...
- idea启动不了,报错Address localhost:1099 is already in use
解决方法 win + R 然后输入cmd netstat -ano|findstr 1099 taskkill -f -pid 你的PID
- Android5以后WebView闪退问题
Android4.4开发项目中的webview在Android各个版本运行的飞起,可是项目升级,最低版本适配5.0之后,webview各种闪退问题 真让人头大!!!!!!!!!!!!!!! 啊啊啊啊啊 ...
- 数据库连接池——C3P0&Druid(快速入门)
数据库连接池--C3P0&Druid (一) 数据库连接池 每一个事物都有其存在的意义,在初学jdbc的时候,我们建立数据库连接对象后,会对其进行释放,但是数据库连接的建立和关闭是非常消耗资源 ...
- 拯救你丢失的精度——BigInteger和BigDecimal类(入门)
第三阶段 JAVA常见对象的学习 BigInteger和BigDecimal类 BigInteger类 (一) 构造方法: //针对超过整数范围的运算(整数最大值:2147483647) BigInt ...
- Spark Scala当中reduceByKey(_+_) reduceByKey((x,y) => x+y)的用法
[学习笔记] reduceByKey(_+_)是reduceByKey((x,y) => x+y)的一个 简洁的形式*/ val rdd08 = sc.parallelize(List((1, ...
- JDBC 资源绑定器 ,处理查询结果集
使用资源绑定器绑定属性配置 实际开发中不建议把连接数据库的信息写死到Java程序中 //使用资源绑定器绑定属性配置 ResourceBundle bundle = ResourceBundle.get ...