Python uses the first-class function to implement the design mode, and the python Design Mode
Case study: Restructuring the "Policy" Model
Some design patterns can be simplified if the functions used as first-class objects are reasonably used, and the "Policy" pattern is a good example.
Classic "policy" Mode
UML class diagram for processing order discounts in "policy" Design Mode
The e-commerce industry has a feature that can obviously use the "Policy" model, that is, calculate the discount based on the customer's attributes or the goods in the order.
Assume that an online store has the following discount rules:
- Customers with 1000 or more credits enjoy a 5% discount for each order
- If the number of a single product in a single order reaches 20 or more, the discount is 10%.
- If there are 10 or more different products in the order, you will enjoy a 7% discount.
For simplicity, we assume that one order can only enjoy one discount at a time.
Context
Entrust some calculations to interactive components that implement different algorithms to provide services. In this instance, the context is Order, which calculates the promotion discount based on different algorithms.
Policy
Implements the common interface of components of different algorithms. In this instance, the abstract class named Promotion assumes this role.
Specific policies
The specific subclass of the policy. FidelityPromo, BulkPromo, and LargeOrderPromo are the three specific policies implemented here.
1 from abc import ABC, abstractmethod 2 from collections import namedtuple 3 4 5 Customer = namedtuple ('customer', 'name fidelity ') 6 7 8 class LineItem: 9 10 def _ init _ (self, product, quantity, price): 11 self. product = product 12 self. quantity = quantity 13 self. price = price 14 15 def total (self): 16 return self. price * self. quantity 17 18 19 class Order: 20 21 def _ init _ (self, customer, cart, promotion = None): 22 self. customer = customer 23 self. cart = list (cart) 24 self. promotion = promotion 25 26 def total (self): 27 if not hasattr (self, '_ total'): 28 self. _ total = sum (item. total () for item in self. cart) 29 return self. _ total 30 31 def due (self): 32 if self. promotion is None: 33 discount = 0 34 else: 35 discount = self. promotion. discount (self) 36 return self. total ()-discount 37 38 def _ repr _ (self): 39 fmt = '<Order total :{:. 2f} due :{:. 2f}> '40 return fmt. format (self. total (), self. due () 41 42 class Promotion (ABC): 43 44 @ brief actmethod 45 def discount (self, order): 46 "Return discount Amount (positive value) "47 48 49 class FidelityPromo (Promotion ): # The first specific policy 50 "provides a 1000 discount for customers with points above 5%" 51 52 def discount (self, order): 53 return order. total ()*. 05 if order. customer. fidelity & gt; = 1000 else 0 54 55 56 class BulkItemPromo (Promotion ): # The second specific policy 57 "10% discount for 20 or more items" 58 59 def discount (self, order ): 60 discount = 0 61 for item in order. cart: 62 if item. quantity> = 20: 63 discount + = item. total ()*. 1 64 return discount 65 66 67 class LargeOrderPromo (Promotion ): # The third specific policy 68 "7% discount" 69 70 def discount (self, order) for 10 or more different products in an order ): 71 distinct_items = {item. product for item in order. cart} 72 if len (distinct_items)> = 10: 73 return order. total ()*. 07 74 return 0 75 76 77 # two customers: joe's credit is 0, ann's credit is 1100 78 joe = Customer ('John Doe ', 0) 79 ann = Customer ('ann Smith ', 1100) 80 81 # shopping cart 82 cart = [LineItem ('banana', 4 ,. 5), 83 LineItem ('apple', 10, 1.5), 84 LineItem ('waterellon', 5, 5.0) 85] 86 87 # fidelityPromo didn't offer joe a discount of 88 print ('Joe 0 points: ', Order (joe, cart, FidelityPromo () 89 # ann got a 5% discount, because her points exceed 1000 90 print ('ann 1000 points: ', Order (ann, cart, FidelityPromo ())) 91 92 #30 bananas and 10 apples in banana_cart 93 banana_cart = [LineItem ('banana ', 30 ,. 5), 94 LineItem ('apple', 10, 1.5) 95] 96 97 # BulkItemPromo offers a 1.50 $98 print ('Joe banana cart :', order (joe, banana_cart, BulkItemPromo () 99 100 # There are 10 different products in long_order. The price of each product is 1.00 USD 101 long_order = [LineItem (str (item_code ), 1, 1.0) for item_code in range (10)] 102 103 # LargerOrderPromo provides a 7% discount of 104 print ('Joe 10 different products :', order (joe, long_order, LargeOrderPromo () 105 print (Order (joe, cart, LargeOrderPromo ()))
The result of the above code execution is:
Joe 0 points: <Order total: 42.00 due: 42.00> ann 1000 points: <Order total: 42.00 due: 39.90> joe banana cart: <Order total: 30.00 due: 28.50> joe 10 different products: <Order total: 10.00 due: 9.30> <Order total: 42.00 due: 42.00>
Implement "policy" mode using functions