python implementation strategy mode

python implementation strategy mode

 

Original Address

1, Strategy Mode Overview

Policy Model : defining a series of algorithms, and marked them encapsulate, and the interchangeable therebetween. This mode allows the algorithm change does not affect customers using the algorithm.

There is a field of electronic business use "policy" mode classic case, that discount is calculated based on the customer's property or order goods.

If a shop has developed the following discount rules.

  • There are 1000 or more points customers, enjoy a 5% discount for each order.

  • The same order, the number of individual commodities reached 20 or above enjoy a 10% discount.

  • Orders different goods to reach 10 or more, enjoy a 7% discount.

For simplicity, we assume that an order can only enjoy a discount.

UML class diagram as follows:

 

Promotion abstract class provides a common interface to different algorithms, fidelityPromo, BulkPromo and LargeOrderPromo three subclasses implement specific "strategies", specific strategies by the customer context class choice.

In this example, prior to instantiate an order (Order type), the system will choose a promotional discount policy in some way, then pass it on to Order constructor. How specific selection strategy, not within the terms of reference of this model. (Selection strategy can use the factory mode.)

 

 2, the traditional method implementation strategy pattern:

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 not hasattr(self, '__total'):
            self.__total = sum(item.total() for item in self.cart)
        return self.__total

    defDue (Self):
         IF self.promotion IS None: 
            Discount = 0
         the else : 
            Discount = self.promotion.discount (Self)
         return self.total () - Discount 

    DEF  __repr__ (Self): 
        FMT = ' <total order: { : .2f}-pocket: {: .2f}> ' 
        return fmt.format (self.total (), self.due ()) 


class Promotion (the ABC):   # policy: an abstract base class 
    @abstractmethod
     DEF Discount (Self, the Order):
         "" " returns the discount amount (value) " ""


class FidelityPromo (Promotion):   # of a specific strategy 
    . "" " 1000 or more to provide customers with a 5% discount points for " "" 
    DEF the Discount (Self, the Order):
         return order.total () * 0.05 IF order.customer .fidelity> = 1000 the else 0 


class BulkItemPromo (Promotion):   # The second specific strategy 
    "" " individual product 10% discount of 20 or more " "" 
    DEF discount (Self, Order): 
        discount = 0
         for Item in order.cart:
             IF item.quantity> = 20 : 
                the DiscountItem.total = + () * 0.1
         return the Discount 


class LargeOrderPromo (Promotion):   # The third specific strategy 
    "" " order to provide different goods reached 7% discount for 10 or more " "" 
    DEF the Discount (Self, the Order ): 
        distinct_items = {item.product for Item in order.cart}
         IF len (distinct_items)> = 10 :
             return order.total () * 0.07
         return 0 


Joe = the Customer ( ' John Doe ' , 0) 
Ann = the Customer ( ' Smith Ann ' ,1100)

Cart = [the LineItem ( ' Banana ' ,. 4, 0.5 ), 
        the LineItem ( ' Apple ' , 10, for 1.5 ), 
        the LineItem ( ' watermellon ' ,. 5, 5.0 )] 

Print ( ' strategy a: is the integral is 1000 or more customer providing 5% discount ' )
 Print (the Order (Joe, Cart, FidelityPromo ()))
 Print (the Order (Ann, Cart, FidelityPromo ())) 

banana_cart = [the LineItem ( ' Banana ' , 30, 0.5 ), 
               the LineItem ( ' Apple ' , 10, 1.5)] 

Print ( ' Strategy II: individual commodities 10% discount of 20 or more as a ' )
 Print (the Order (Joe, banana_cart, BulkItemPromo ())) 

long_order = [the LineItem (STR (ITEM_CODE),. 1, 1.0) for ITEM_CODE in the Range (10 )] 

Print ( ' strategy III: 7% discount on orders of different goods to reach 10 or more ' )
 Print (the Order (joe, long_order, LargeOrderPromo ()))
 Print (the Order (joe, the Cart , LargeOrderPromo ()))

Output:

Strategy One: to provide customers with 1000 or more points for the 5% discount
 <Order Total: 42.00 out of pocket: 42.00> 
<Orders Total: 42.00 out of pocket: 39.90> 
offers 10 individual commodities is 20 or more when: Strategy II % discount
 <Order total: 30.00 out of pocket: 28.50> 
strategy three: the order of different goods to reach the offer 7:10 or more % discount
 <Order total: 10.00 out of pocket: 9.30> 
<orders total: 42.00 out of pocket : 42.00>

 

 

3, use the function implementation strategy mode

In traditional methods mode, each category is a particular strategy, but only defines a method, in addition to any other instance properties. They look like ordinary function the same. Indeed, in Python, we can put specific strategies into a simple function, and remove policies abstract class.

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 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 = ' <total order: {: .2f}-pocket: {: .2f}> ' 
        return fmt.format (self.total (), self.due ()) 


DEF fidelity_promo (the Order):
     "" " provides a 5% discount or more points for the customer 1000 " "" 
    return order.total () * .05 IF order.customer .fidelity> = 1000 the else 0 


DEF bulk_item_promo (Order):
     "" " 10% discount when 20 or more individual commodity " ""
    discount = 0
    for Item in order.cart:
         IF item.quantity> = 20 is : 
            Discount + = item.total () * .1
     return Discount 


DEF : large_order_promo (Order)
     "" " to provide 7 different orders of goods to reach 10 or more % discount "" " 
    distinct_items = {item.product for Item in order.cart}
     IF len (distinct_items)> = 10 :
         return order.total () * .07
     return 0 


Joe = the Customer ( ' John Doe ' , 0) 
Ann = Customer (' Ann Smith ' , 1100 is ) 

Cart = [the LineItem ( ' Banana ' ,. 4, 0.5 ), 
        the LineItem ( ' Apple ' , 10, for 1.5 ), 
        the LineItem ( ' watermellon ' ,. 5, 5.0 )] 

Print ( ' Strategy One: To Points 1000 or more customers 5% discount ' )
 Print (the Order (Joe, Cart, fidelity_promo))
 Print (the Order (Ann, Cart, fidelity_promo)) 

banana_cart = [the LineItem ( ' Banana ' , 30, 0.5 ), 
               the LineItem (' Apple ' , 10, for 1.5 )] 

Print ( ' Strategy II: individual commodities 10% discount of 20 or more as a ' )
 Print (the Order (Joe, banana_cart, bulk_item_promo)) 

long_order = [the LineItem (STR (ITEM_CODE), . 1, 1.0) for ITEM_CODE in Range (10 )] 

Print ( ' strategy III: 7% discount for 10 or more orders of different goods reach ' )
 Print (the Order (Joe, long_order, large_order_promo))
 Print (the Order ( joe, cart, large_order_promo))
In fact, as long as the language supports higher-order functions, so you can achieve, such as C # , you can achieve with the commission. Just so the code becomes complex to achieve but do not understand. And Python, the native function may be passed as a parameter.

It is worth noting, "Design Patterns: Elements of Reusable Object-Oriented Software" author of the book said:. "Policy Objects usually a good Flyweight" Flyweight is a shared object that can be simultaneously in multiple contexts use. Sharing is a recommended practice, this need not be in every new context (here Order example) continue to create a new specific policy object when using the same strategy to reduce consumption. Therefore, in order to avoid [the strategy pattern] run-time consumption, it can be used in conjunction with [Flyweight], but this way, the number of lines of code and maintenance costs will continue to rise.

In complex cases, when the need for specific strategies to maintain internal state, you may need to "strategy" and "Flyweight" pattern together. However, no specific strategy will typically internal state, but the data processing context. In this case, be sure to use common functions, not only to write a class method, go to another class implementing a single-function interface declarations. Examples of functions than the lightweight user-defined classes, and without the use of "Flyweight" mode, because each policy function when compiling Python module will only be created once. Common functions are "shared object can be used simultaneously in multiple contexts."

 

Guess you like

Origin www.cnblogs.com/-wenli/p/10963391.html