Python学习之路25-使用一等函数实现设计模式

匿名 (未验证) 提交于 2019-12-02 22:54:36

《流畅的Python》笔记。

本篇主要讲述Python中使用函数来实现策略模式和命令模式,最后总结出这种做法背后的思想。

策略模式如果用面向对象的思想来简单解释的话,其实就是“多态”。父类指向子类,根据子类对同一方法的不同重写,得到不同结果。

下图是经典的策略模式的UML类图:

《设计模式:可复用面向对象软件的基础》一书这样描述策略模式:

定义一系列算法,把它们封装起来,且使它们能相互替换。本模式使得算法可独立于使用它的客户而变化。

下面以一个电商打折的例子来说明策略模式,打折方案如下:

  • 有1000及以上积分的顾客,每个订单享5%优惠;
  • 同一订单中,每类商品的数量达到20个及以上时,该类商品享10%优惠;
  • 订单中的不同商品达10个及以上时,整个订单享7%优惠。

为此我们需要创建5个类:

  • Order类:订单类,相当于上述UML图中的Context上下文;
  • Promotion类:折扣类的父类,相当于UML图中的Strategy策略类,实现不同策略的共同接口;
  • 具体策略类:FidelityPromoBulkPromoLargeOrderPromo依次对应于上述三个打折方案。

以下是经典的策略模式在Python中的实现:

from abc import ABC, abstractmethod from collections import namedtuple  Customer = namedtuple("Customer", "name fidelity")  class LineItem:  # 单个商品     def __init__(self, product, quantity, price):         self.produce = 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)  # 形参cart中的元素是LineItem         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  class Promotion(ABC): # 策略:抽象基类     @abstractmethod  # 抽象方法     def discount(self, order):         """返回折扣金额(正值)"""  class FidelityPromo(Promotion): # 第一个具体策略     """积分1000及以上的顾客享5%"""     def discount(self, order):         return order.total() * 0.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:        
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!