摘要:前言合理使用作為一等對象的函數,可以使某種設計模式得以簡化。本例中這個抽象類扮演這個角色。此外,策略實例沒有狀態實例屬性使用函數代替抽象類,每個策略都是函數,不必實例化,拿來即用。
前言
合理使用作為一等對象的函數,可以使某種設計模式得以簡化。關于策略
定義一系列算法,把它們一一封裝起來,并且使它們可以相互替換。一個策略模式的示例
規則
1 有1000或以上積分的客戶,每個訂單享受5%的折扣。 2 同一個訂單中,單個商品的數量達到20個或以上,享受10%折扣。 3 訂單中的不同商品數達到10個或以上,享受7%折扣。
策略模式
上下文
把一些計算委托給實現不同算法的可互換組件,它提供服務。本例中,上下文是Order,它會根據不同的算法計算促銷折扣
策略
實現不同算法的組件共同的接口。本例中Promotion這個抽象類扮演這個角色。
具體策略
策略的具體子類。本例中為 fidelityPromo, BulkPromo, LargeOrderPromo三個子類。經典模式
#!/usr/bin/env python # -*- coding: utf-8 -*- # @File : ex1.py # @Time : 18/10/09 17:01 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 = 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.discount(self) return self.total() - discount def __repr__(self): fmt = "函數模式" return fmt.format(self.total(), self.due()) class Promotion(ABC): # 策略:抽象基類 @abstractmethod def discount(self, order): """ 返回折扣金額(正值) :param order: :return: """ 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 # 兩個顧客:joe的積分為0,ann的積分是1100 joe = Customer("John Doe", 0) ann = Customer("Ann Smith", 1100) # 有3個商品的購物車 cart = [LineItem("banana", 4, .5), LineItem("apple", 10, 1.5), LineItem("watermellon", 5, 5.0)] # joe未享受到折扣,ann享受到了5%折扣 ex1 = Order(joe, cart, FidelityPromo()) ex2 = Order(ann, cart, FidelityPromo()) # banana數量超過20個,joe享受到了10%的折扣 banana_cart = [LineItem("banana", 30, .5), LineItem("apple", 10, 1.5)] ex3 = Order(joe, banana_cart, BulkItemPromo()) # 商品數量超過了10個,為joe提供了7%的折扣 long_order = [LineItem(str(item_code), 1, 1.0) for item_code in range(10)] ex4 = Order(joe, long_order, LargeOrderPromo()) ex5 = Order(joe, cart, LargeOrderPromo()) print(ex1) print(ex2) print(ex3) print(ex4) print(ex5)
#!/usr/bin/env python # -*- coding: utf-8 -*- # @File : ex2.py # @Time : 18/10/10 10:46 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 = 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 = "對比" return fmt.format(self.total(), self.due()) def fidelity_promo(order): return order.total() * .05 if order.customer.fidelity >= 1000 else 0 def bulk_item_promo(order): discount = 0 for item in order.cart: if item.quantity >= 20: discount += item.total() * .1 return discount def large_order_promo(order): distinct_items = {item.product for item in order.cart} if len(distinct_items) >= 10: return order.total() * .07 return 0 # 兩個顧客:joe的積分為0,ann的積分是1100 joe = Customer("John Doe", 0) ann = Customer("Ann Smith", 1100) # 有3個商品的購物車 cart = [LineItem("banana", 4, .5), LineItem("apple", 10, 1.5), LineItem("watermellon", 5, 5.0)] eg1 = Order(joe, cart, fidelity_promo) eg2 = Order(ann, cart, fidelity_promo) banana_cart = [LineItem("banana", 30, .5), LineItem("apple", 10, 1.5)] eg3 = Order(joe, banana_cart, bulk_item_promo) long_order = [LineItem(str(item_code), 1, 1.0) for item_code in range(10)] eg4 = Order(joe, long_order, large_order_promo) print(eg1," ", eg2, " ", eg3, " ", eg4)
經典模式中每個具體策略都是一個類,而且只定義了一個方法,即discount。此外,策略實例沒有狀態(實例屬性)
使用函數代替抽象類,每個策略都是函數,不必實例化,拿來即用。新的Order類使用起來更簡單,代碼行數更少。參考
<<流暢的Python>>
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42605.html
摘要:本篇主要講述中使用函數來實現策略模式和命令模式,最后總結出這種做法背后的思想。 《流暢的Python》筆記。本篇主要講述Python中使用函數來實現策略模式和命令模式,最后總結出這種做法背后的思想。 1. 重構策略模式 策略模式如果用面向對象的思想來簡單解釋的話,其實就是多態。父類指向子類,根據子類對同一方法的不同重寫,得到不同結果。 1.1 經典的策略模式 下圖是經典的策略模式的U...
摘要:做前端開發已經好幾年了,對設計模式一直沒有深入學習總結過。今天第一天,首先來講策略模式。什么是策略模式四兄弟的經典設計模式中,對策略模式的定義如下定義一系列的算法,把它們一個個封裝起來,并且使它們可互相替換。 做前端開發已經好幾年了,對設計模式一直沒有深入學習總結過。隨著架構相關的工作越來越多,越來越能感覺到設計模式成為了我前進道路上的一個阻礙。所以從今天開始深入學習和總結經典的設計模...
摘要:哪吒社區技能樹打卡打卡貼函數式接口簡介領域優質創作者哪吒公眾號作者架構師奮斗者掃描主頁左側二維碼,加入群聊,一起學習一起進步歡迎點贊收藏留言前情提要無意間聽到領導們的談話,現在公司的現狀是碼農太多,但能獨立帶隊的人太少,簡而言之,不缺干 ? 哪吒社區Java技能樹打卡?【打卡貼 day2...
摘要:續前文后端好書閱讀與推薦,幾十天過去了,又看了兩本好書還有以前看過的書,這里依然把它們總結歸納一下,加入一些自己的看法有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。 續前文 后端好書閱讀與推薦 - Mageek`s Wonderland ,幾十天過去了,又看了兩本好書(還有以前看過的書),這里依然把它們總結歸納一下,加入一些自己的看法、有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。...
摘要:續前文后端好書閱讀與推薦,幾十天過去了,又看了兩本好書還有以前看過的書,這里依然把它們總結歸納一下,加入一些自己的看法有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。 續前文 后端好書閱讀與推薦 - Mageek`s Wonderland ,幾十天過去了,又看了兩本好書(還有以前看過的書),這里依然把它們總結歸納一下,加入一些自己的看法、有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。...
閱讀 2847·2021-09-10 10:51
閱讀 2215·2021-09-02 15:21
閱讀 3206·2019-08-30 15:44
閱讀 869·2019-08-29 18:34
閱讀 1652·2019-08-29 13:15
閱讀 3322·2019-08-26 11:37
閱讀 2697·2019-08-26 10:46
閱讀 1107·2019-08-26 10:26