第 6 章 使用一等函數實現設計模式
阿新 • • 發佈:2019-03-18
mman 購物車 tuple bulk print method imp col 支持
# 《流暢的Python》讀書筆記 # 第6章 使用一等函數實現設計模式 # 雖然設計模式與語言無關,但這並不意味著每一個模式都能在每一門語言中使用。 # 6.1 案例分析:重構“策略”模式 # 如果合理利用作為一等對象的函數,某些設計模式可以簡化,“策略”模式就是其中一個很好的例子。 # 本節接下來的內容中將說明“策略”模式,並使用《設計模式:可復用面向對象軟件的基礎》一書中所述的“經典”結構實現它。 # 如果你熟悉這個經典模式,可以跳到 6.1.2 節,了解如何使用函數重構代碼來有效減少代碼行數。# 6.1.1 經典的“策略”模式 # 示例 6-1 實現Order類,支持插入式折扣策略 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 def total(self): if nothasattr(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): @abstractmethod def discount(self,order): """"返回折扣金額(正值)""" class FidelityPromo(Promotion): """為積分為1000或以上的顧客提供5%折扣""" def discount(self,order): return order.total()*.05 if order.customer.fidelity>=1000 else 0 class BulkItemPromo(Promotion): """單個商品為20個或以上時提供10%折扣""" def discount(self,order): discount=0 for item in order.cart: if item.quantity>=20: discount += item.total()* .1 return discount class LargeOrderPromo(Promotion): """"訂單中的不同商品達到10個或以上時提供7%折扣""" def discount(self,order): distinct_items={item.product for item in order.cart} if len(distinct_items) >= 10: return order.total()* .07 return 0 # 示例 6-2 使用不同促銷折扣的Order類示例 joe=Customer(‘John Doe‘,0) #joe 的積分是0 ann=Customer(‘Ann Smith‘,1100) #ann 的積分是1100。 cart=[ LineItem(‘banana‘,4,.5), #有三個商品的購物車。 LineItem(‘apple‘,10,1.5), LineItem(‘watermellon‘,5,5.0) ] print(Order(joe,cart,FidelityPromo())) #fidelityPromo 沒給 joe 提供折扣。 #<Order total:42.00 due:42.00> print(Order(ann,cart,FidelityPromo())) #ann 得到了5%折扣,因為她的積分超過 1000。 #<Order total:42.00 due:39.90> banana_cart=[ LineItem(‘banana‘,30,.5), #banana_cart中有30把香蕉和10個蘋果。 LineItem(‘apple‘,10,1.5) ] print(Order(joe,banana_cart,BulkItemPromo())) #BulkItemPromo為joe購買的香蕉優惠了1.50美元。 #<Order total:30.00 due:28.50> long_order=[ LineItem(str(item_code),1,1.0) #long_order中有10個不同的商品,每個商品的價格為1.00美元。 for item_code in range(10) ] print(Order(joe,long_order,LargeOrderPromo())) #LargerOrderPromo 為 joe 的整個訂單提供了 7% 折扣。 #<Order total:10.00 due:9.30> print(Order(joe,cart,LargeOrderPromo())) #<Order total:42.00 due:42.00> # 6.1.2 使用函數實現“策略”模式 # 示例 6-3 Order 類和使用函數實現的折扣策略 # 示例 6-4 使用函數實現的促銷折扣的 Order 類示例 # 6.1.3 選擇最佳策略:簡單的方式 # 示例 6-5 best_promo 函數計算所有折扣,並返回額度最大的 # 示例 6-6 best_promo 叠代一個函數列表,並找出折扣額度最大的 # 6.1.4 找出模塊中的全部策略 # 示例 6-7 內省模塊的全局命名空間,構建 promos 列表 # 示例 6-8 內省單獨的 promotions 模塊,構建 promos 列表 # 6.2 “命令”模式 # 示例 6-9 MacroCommand 的各個實例都在內部存儲著命令列表 # 6.3 本章小結 # 6.4 延伸閱讀
第 6 章 使用一等函數實現設計模式