Python编程:使用一等函数实现设计模式

1. 案例分析:重构“策略”模式

        策略模式:定义一系列的算法,把它们一一封装起来,并且使他们之间可以相互替换。本模式可以使算法独立于使用它的客户而变化。该模式一般分为三个部分:上下文(把一些计算委托给实现不同算法的可互换组件,它提供服务,在下面的例子中,上下文是Order),策略(实现不同算法的组件的共同接口,在下面的例子中,策略是Promotion),具体策略(策略的子类,在下面的例子中,具体策略是fidelityPromo、BulkPromo、LargeOrderPromo)。

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 tocal(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.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 FidelityProm(Promotion):
    """积分为1000或者以上的顾客享受5%折扣"""
    def discount(self, order):
        return order.total() * 0.05 if order.fidelity >= 1000 else 0

class BulkItemProm(Promotion):
    """单个样品数量为10个以上时提供10%的折扣"""
    def discount(self, order):
        discount = 0
        for item in order.cart:
            if item.quantity >=20:
                discount += item.total() * 0.1
        return discount

class LargeOrderPromo(Promotion):
    """订单中的商品达到十个或以上是提供%7的折扣"""
    def discount(self, order):
        distinct_items = {item.product for item in order.cart}
        if len(distinct_items) >= 10:
            return order.total() * 0.07
        return 0

      当然,还可以对上述代码进行优化重构,如:可以把抽象基类通过定义普通的方法来代替。这样,在使用该方法时直接调用函数即可。这样也更好方便一些。

2.“命令”模式

        “命令”设计模式也可以把函数作为参数而简化。命令模式的目的是解耦调用操作的对象(调用者)和提供实现对象(接受者)。这个模式的做法是在二者之间放一个Command对象,让它实现只有一个方法(execute)的接口,调用接收者中的方法实现所需的操作。

       当然,我们还可以不为调用者提供一个Command实例,而是给它一个函数。在下段代码中,定义了一个call方法,使command命令能依次执行。当然,如果我们还有需要,可以自己定以其他的方法。

class MacroCommand:
    def __init__(self, commands):
        self.commands = list(commands)
    def __call__(self):
        for command in self.commands:
            command()

       值得注意的是,在Python中使用函数和可调用的对象实现回调会更自然一些。这比上面所说的策略和命令模式更好一些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值