zoukankan      html  css  js  c++  java
  • python高级(六)——用一等函数实现设计模式

    本文主要内容

    经典的“策略”模式

     

    python高级——目录

    文中代码均放在github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

    经典的“策略”模式

    '''
        经典的策略模式:
            封装一系列可以互相替代的算法,使得算法可以独立与使用它的客户而变化。
    
    
        假设当代商城某服装店有以下三种打折规则:
            1、对于会员,全部商品8.5折
            2、同一件商品买两件及以上,除第一件外,剩余的7.5折
            3、买上5件不同商品,全部商品打8折
        三种规则只能享受一个。
    '''
    
    
    from abc import ABC, abstractmethod
    from collections import namedtuple
    
    Customer = namedtuple('Customer', 'name vip')     # 消费者对象
    
    
    class Clothing:                # 服装类
    
        def __init__(self, name, quantity, price):
            self.name = name
            self.quantity = quantity
            self.price = price
    
        def total(self):
            return self.price * self.quantity
    
    
    class Order:  # 订单类
    
        def __init__(self, customer, clothing, promotion=None):
            self.customer = customer
            self.clothing = list(clothing)
            self.promotion = promotion
    
        def total(self):
            if not hasattr(self, '__total'):
                self.__total = sum(item.total() for item in self.clothing)
            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):
            ''':returns 计算折扣'''
    
    
    class VipPromo(Promotion):  # 会员折扣
        """:returns 会员8.5折"""
    
        def discount(self, order):
            return order.total() * .15 if order.customer.vip  else 0
    
    
    class TwoPromo(Promotion):  # 第二个
        ''':returns 同一件衣服两件以上,第二件及之后的7.5折'''
    
        def discount(self, order):
            discount = 0
            for item in order.clothing:
                if item.quantity >= 2:
                    discount += (item.total() - item.price) * .25
            return discount
    
    
    class FivePromo(Promotion):  # 5种以上
        """ :returns 买5种不同服装以上,每件8折"""
    
        def discount(self, order):
            distinct_items = {item.name for item in order.clothing}
            if len(distinct_items) >= 5:
                return order.total() * .2
            return 0
    
    
    if __name__ == "__main__":
        # 创建消费者
        joe = Customer('John Doe', 0)  # 非会员
        ann = Customer('Ann Smith', 1) # 会员
    
        # 创建购物车
        clothing = [Clothing('pants', 6, 200),
                    Clothing('skirt', 1, 150),
                    Clothing('shoes', 2, 230)]
        print(Order(joe, clothing, VipPromo()))  #   <Order total: 1810.00 due: 1810.00>    不是会员,不打折
        print(Order(ann, clothing, VipPromo()))  #   <Order total: 1810.00 due: 1538.50>    会员,打85折
    
    
        print(Order(joe, clothing, TwoPromo()))  # <Order total: 1810.00 due: 1502.50>   两件以上7.5折
        print(Order(joe, clothing, FivePromo())) # <Order total: 1810.00 due: 1810.00>   没到5种不打折
    
        clothing.extend([Clothing('shirt', 1, 90), Clothing('bra', 2, 130)])
        print(Order(joe, clothing, FivePromo())) # <Order total: 2160.00 due: 1728.00>  刚好5种打8折
    '''
        下面使用函数完成"经典"策略
    '''
    
    from abc import ABC, abstractmethod
    from collections import namedtuple
    
    Customer = namedtuple('Customer', 'name vip')     # 消费者对象
    
    
    class Clothing:                # 服装类
    
        def __init__(self, name, quantity, price):
            self.name = name
            self.quantity = quantity
            self.price = price
    
        def total(self):
            return self.price * self.quantity
    
    
    class Order:  # 订单类
    
        def __init__(self, customer, clothing, promotion=None):
            self.customer = customer
            self.clothing = list(clothing)
            self.promotion = promotion
    
        def total(self):
            if not hasattr(self, '__total'):
                self.__total = sum(item.total() for item in self.clothing)
            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 VipPromo(order):  # 会员折扣
        return order.total() * .15 if order.customer.vip  else 0
    
    
    def TwoPromo(order):  # 第二个
        discount = 0
        for item in order.clothing:
            if item.quantity >= 2:
                discount += (item.total() - item.price) * .25
        return discount
    
    
    def FivePromo(order):  # 5种以上
        distinct_items = {item.name for item in order.clothing}
        if len(distinct_items) >= 5:
            return order.total() * .2
        return 0
    
    
    
    if __name__ == "__main__":
        # 创建消费者
        joe = Customer('John Doe', 0)  # 非会员
        ann = Customer('Ann Smith', 1) # 会员
    
        # 创建购物车
        clothing = [Clothing('pants', 6, 200),
                    Clothing('skirt', 1, 150),
                    Clothing('shoes', 2, 230)]
        print(Order(joe, clothing, VipPromo))  #   <Order total: 1810.00 due: 1810.00>    不是会员,不打折
        print(Order(ann, clothing, VipPromo))  #   <Order total: 1810.00 due: 1538.50>    会员,打85折
    
    
        print(Order(joe, clothing, TwoPromo))  # <Order total: 1810.00 due: 1502.50>   两件以上7.5折
        print(Order(joe, clothing, FivePromo)) # <Order total: 1810.00 due: 1810.00>   没到5种不打折
    
        clothing.extend([Clothing('shirt', 1, 90), Clothing('bra', 2, 130)])
        print(Order(joe, clothing, FivePromo)) # <Order total: 2160.00 due: 1728.00>  刚好5种打8折
        promos = [VipPromo, TwoPromo, FivePromo]
    
    
        def best_stratety(order):
            return max(promo(order) for promo in promos)
    
    
        print(Order(joe, clothing, best_stratety))   # <Order total: 2160.00 due: 1728.00>  自动选择最优的策略
    '''
        使用globals函数找出当前的全局号。其返回的是字典格式
    '''
    promos = [globals()[name] for name in globals()
                  if name.endswith("Promo")]
    
        print(promos)   #  找到了三个策略函数 [<function FivePromo at 0x10c363b70>, <function TwoPromo at 0x10c363ae8>, <function VipPromo at 0x10abd3048>]
    
        def best_stratety(order):
            return max(promo(order) for promo in promos)
    
    print(Order(ann, clothing, best_stratety))  #<Order total: 2160.00 due: 1728.00>
    '''
       我们可以创建一个类,管理所有命令,并且将其实例重写为可调用对象
    '''
    
    class MacroCommand:
        def __init__(self, commands):
            self.commands = list(commands)
    
        def __call__(self):
            for command in self.commands:
                command()

    python高级系列文章目录

    python高级——目录

  • 相关阅读:
    Miller-Rabin算法
    拟阵
    第一次作业
    实验四 201771010101 白玛次仁
    201771010101 白玛次仁
    201771010101 白玛次仁 《2018面向对象程序设计(Java)课程学习进度条》
    201771010101 白玛次仁
    201771010101 白玛次仁
    达拉草201771010105《面向对象程序设计(java)》第二周学习总结
    达拉草201771010105《面向对象程序设计(java)》第一周学习总结
  • 原文地址:https://www.cnblogs.com/liao-sir/p/8493915.html
Copyright © 2011-2022 走看看