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的更多相关文章

  1. Learning JavaScript Design Patterns The Module Pattern

    The Module Pattern Modules Modules are an integral piece of any robust application's architecture an ...

  2. Design Patterns Example Code (in C++)

    Overview Design patterns are ways to reuse design solutions that other software developers have crea ...

  3. 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 ...

  4. Design Patterns Simplified - Part 3 (Simple Factory)【设计模式简述--第三部分(简单工厂)】

    原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part3-factory/ Design ...

  5. Design Patterns Simplified - Part 2 (Singleton)【设计模式简述--第二部分(单例模式)】

    原文链接: http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part-2-singleton/ De ...

  6. Head First Design Patterns

    From Head First Design Patterns. Design Principle: Idnetify the aspects of your application that var ...

  7. Apex Design Patterns

    Apex allows you to build just about any custom solution on the Force.com platform. But what are the ...

  8. [Design Patterns] 4. Creation Pattern

    设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结,使用设计模式的目的是提高代码的可重用性,让代码更容易被他人理解,并保证代码可靠性.它是代码编制真正实现工程化. 四个关键元素 ...

  9. [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. 软件模 ...

  10. [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 ...

随机推荐

  1. 数据集成、变换、归约及相关MATLAB工具箱函数

    数据预处理的主要内容包括数据清洗.数据集成.数据变换和数据规约,在数据挖掘的过程中,数据预处理工作量占到了整个过程的60%.数据清洗在上一篇博客中写过,这里主要写后面三部分. 数据集成 数据挖掘需要的 ...

  2. glide包管理工具

    上一篇文章中我们已经成功的运行了go的代码,这是我们迈出的最基础的一步. 一个项目通常会依赖很多外部的库,当依赖的库比较多的时候,手工管理就会比较麻烦,这个时候就需要包管理工具出场了,帮你管理好所有依 ...

  3. mysql/mariadb数据库在插入表数据时,ID竟然成奇数增加了?看完下面内容就知道怎么处理了。

    今天突然被问到一个问题,mysql数据库插入表数据时,设置了ID自增,但是插入数据后,ID却呈奇数增加,不是123456类型,而是13579形式,突然有点懵,研究了一会,发现是auto_increme ...

  4. appium(toast处理)

    from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expec ...

  5. sql注入02

    第一关:基于错误的get单引号字符型注入 第二关:基于错误的get整形注入 第三关:基于错误的get单引号变形字符型注入 第四关:基础错误的双引号字符型注入 第五关: 第六关 第七关:导出文件get字 ...

  6. CImage 和 CvvImage 命名空间问题

    [问题:名称CImage同时在两个库中出现] 1.出现: ATL #include <atlimage.h> OpenCv #include <highgui.h> #defi ...

  7. jquery清除元素的点击事件

    $("#id").css("pointer-events", "none");

  8. golang语言sql Rows转化保存成map

    func DoQuery(db *sql.DB, sqlInfo string, args ...interface{}) ([]map[string]interface{}, error) { ro ...

  9. shell备份脚本

    #!/bin/bash #不存在的变量终止脚本执行 set -o nounset #执行出错终止脚本执行 set -o errexit #递归列出文件的绝对路径并执行压缩 delDir=`date - ...

  10. Python 解LeetCode:33. Search in Rotated Sorted Array

    题目描述:在一个旋转数组中查找给定的值,其中旋转数组中不含重复值: 思路: 第一遍二分遍历,找到数组中最小值的索引: 第二遍分别对最小值左右两边的数组进行二分查找: class Solution(ob ...