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. C# 实现启用或停止本地网络连接

    获取本机网络连接列表 public static List<string> GetNetList() { List<string> ls = new List<strin ...

  2. 安装mysqlmysql-5.7.24-linux-glibc2.12-x86_64

    1.下载mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz(/opt目录) 2.tar -zxvf mysql-5.7.24-linux-glibc2.12-x86_ ...

  3. 源码分析之AsyncTask

    AsyncTask在Android中是很常用的异步线程,那么AsyncTask和Thread有什么区别呢?这里将从源码角度深入理解AsyncTask的设计和工作原理,这里的AsyncTask基于SDK ...

  4. 最新 易车java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.易车等10家互联网公司的校招Offer,因为某些自身原因最终选择了易车.6.7月主要是做系统复习.项目复盘.LeetCode ...

  5. UWP笔记-使用FFmpeg编解码

    在开发UWP媒体应用的时候,使用的MediaElement可以支持主流的格式,不过还是有些格式本地编解码器是不支持的,如.flv..rmvb等,这里讲到的是第三方开源库FFmpeg,可以直接播放更多的 ...

  6. 究竟什么是Java异常?

    第四阶段 IO 异常处理 没有完美的程序,所以我们需要不断地完善,考虑各种可能性,我们要将除了自己以外的任何用户或者操作者都当成傻子来考虑问题 在我们开发过程中 我们运行时常常会遇到 这样java.l ...

  7. flannel vxlan工作基本原理及常见排障方法

    写在前面 最近用kubeadm鼓捣了几个cluster集群测试用,网络用的flannel.因为这些机器都不是纯净的环境(以前部署过其他的k8s或者有一些特别的设置),所以部署起来遇到了很多问题.看了下 ...

  8. (十)springMvc 校验

    目录 文章目录 目录 @[toc] springMvc 校验 准备 踩坑 配置校验器 将校验器注入到适配器中 在 pojo 中配置校验规则 在 controller 层进行检验 获取错误信息 将错误信 ...

  9. 数据结构C++实现-第一章 绪论

    1.1 计算机与算法 1.1.3 起泡排序 void bubbleSort(int a[], int n) { for(bool sorted=false; !sorted; --n) { sorte ...

  10. MySQL 并发事务问题以及事务的隔离级别

    一.并发事务处理带来的问题 相对于串行处理,并发事务(InnoDB)处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从而可以支持更多用户. 但并发事务处理也会带来一些问题,主要有一下几种 ...