流畅的python第六章 使用一等函数设计模式

使用一等函数实现设计模式
这里我们以策略模式来讲解
定义一系列算法, 把他们封装起来, 并且使他们可以相互替换, 可以使算法独立于使用它的客户而变化

主要目的就是为了让任意买家以任意 打折方案清空任意购物车三者任意结合给出最终金额

  • 购物车包括 订单数组 , 买家 , 打折方案
  1. 订单数组由一系列订单组成
  2. 买家包括买家姓名,买家积分
  3. 打折方案只有一个折扣方法, 传入购物车本身

这是购物车的类图
在这里插入图片描述

目录

  1. 用类实现购物车策略模式
  2. 用一等函数实现购物车的策略模式
  3. 全部策略
  4. 最佳的策略模式

1. 用类实现购物车策略模式

使用类的思路来实现

# -*- coding: utf-8 -*- 

from collections import namedtuple
from abc import abstractmethod

# 具名元组
Customer = namedtuple('Customer', 'name, credits')


class ShopCart(object):
	"""购物车"""

	def __init__(self, orders, customer, promotion):
		"""

		:type promotion: Promotion
		:type orders: Order
		"""
		self._orders = orders
		self._customer = customer
		self._promotion = promotion

	@property
	def customer(self):
		return self._customer

	@property
	def orders(self):
		return self._orders

	def total(self):
		if not hasattr(self, '_total'):
			self._total = sum([item.total() for item in self.orders])
		return self._total

	def due(self):
		if self._promotion:
			return self.total() - self._promotion.discount(self)
		return self.total()

	def __repr__(self):
		fmt = '<total: {:.2f} due: {:.2f}>'
		return fmt.format(self.total(), self.due())


class Order(object):

	def __init__(self, production, quantity, price):
		self._production = production
		self._quantity = quantity
		self._price = price

	@property
	def production(self):
		return self._production

	@property
	def quantity(self):
		return self._quantity

	@property
	def price(self):
		return self._price

	def total(self):
		return self.quantity * self.price


class Promotion(object):
	"""折扣父类"""
	@abstractmethod
	def discount(self, shop_cart):
		"""
		:type shop_cart: ShopCart
		"""


class GoodCustomerPromotion(Promotion):
	"""1000分以上5%折扣"""

	def __init__(self):
		super(GoodCustomerPromotion, self).__init__()

	def discount(self, shop_cart):
		if shop_cart.customer.credits >= 1000:
			return shop_cart.total() * .05
		return 0


class SigletonProductionPromotion(Promotion):
	"""单个商品20个以上 10%折扣"""

	def __init__(self):
		super(SigletonProductionPromotion, self).__init__()

	def discount(self, shop_cart):
		result = 0
		for item in shop_cart.orders:
			if item.production > 20:
				result += (item.quantity * item.price) * 0.1
		return result


class ManyDifferentProductionPromotion(Promotion):
	"""不同商品种类10个以上, 给予7%折扣"""

	def __init__(self):
		super(ManyDifferentProductionPromotion, self).__init__()

	def discount(self, shop_cart):
		if len(shop_cart.orders) >= 7:
			return shop_cart.total() * .07
		return 0


# 三个顾客
customer_william = Customer('william', 2000)
customer_zhang = Customer('张冠举', 0)
customer_long = Customer('龙斌', 0)

# 两种购物车
orders_normal = [Order('香蕉', 4, .5), Order('苹果', 10, 1.5), Order('西瓜', 5, 5.0)]
orders_sigleton= [Order('香蕉', 30, .5), Order('苹果', 10, 1.5)]
orders_different = [Order(str(i), 1, 10) for i in range(10)]

print ShopCart(orders_normal, customer_zhang, GoodCustomerPromotion())
print ShopCart(orders_normal, customer_long, GoodCustomerPromotion())
print ShopCart(orders_normal, customer_william, GoodCustomerPromotion())
print ShopCart(orders_sigleton, customer_william, SigletonProductionPromotion())
print ShopCart(orders_different, customer_william, ManyDifferentProductionPromotion())

执行结果
在这里插入图片描述


2. 用一等函数实现购物车的策略模式

然后我们想一下, 在python种, 方法也是对象啊, 上面的那些折扣对象不就是用了一个传入ShopCart对象,返回折扣的方法吗? 那我们完全可以把这些折扣对象写成方法, 然后购物车种拿到这些方法不就行了, 如下:

# -*- coding: utf-8 -*- 
from collections import namedtuple
from abc import abstractmethod

Customer = namedtuple('Customer', 'name, credits')


class ShopCart(object):
	"""购物车"""

	def __init__(self, orders, customer, promotion):
		"""

		:type promotion: Promotion
		:type orders: Order
		"""
		self._orders = orders
		self._customer = customer
		self._promotion = promotion

	@property
	def customer(self):
		return self._customer

	@property
	def orders(self):
		return self._orders

	def total(self):
		if not hasattr(self, '_total'):
			self._total = sum([item.total() for item in self.orders])
		return self._total

	def due(self):
		if self._promotion:
			return self.total() - self._promotion(self)
		return self.total()

	def __repr__(self):
		fmt = '<total: {:.2f} due: {:.2f}>'
		return fmt.format(self.total(), self.due())


class Order(object):

	def __init__(self, production, quantity, price):
		self._production = production
		self._quantity = quantity
		self._price = price

	@property
	def production(self):
		return self._production

	@property
	def quantity(self):
		return self._quantity

	@property
	def price(self):
		return self._price

	def total(self):
		return self.quantity * self.price


def GoodCustomerPromotion(shop_cart):
	"""1000分以上5%折扣"""
	if shop_cart.customer.credits >= 1000:
		return shop_cart.total() * .05
	return 0

def SigletonProductionPromotion(shop_cart):
	result = 0
	for item in shop_cart.orders:
		if item.production > 20:
			result += (item.quantity * item.price) * 0.1
	return result

def ManyDifferentProductionPromotion(shop_cart):
		if len(shop_cart.orders) >= 7:
			return shop_cart.total() * .07
		return 0


# 三个顾客
customer_william = Customer('william', 2000)
customer_zhang = Customer('张冠举', 0)
customer_long = Customer('龙斌', 0)

# 两种购物车
orders_normal = [Order('香蕉', 4, .5), Order('苹果', 10, 1.5), Order('西瓜', 5, 5.0)]
orders_sigleton= [Order('香蕉', 30, .5), Order('苹果', 10, 1.5)]
orders_different = [Order(str(i), 1, 10) for i in range(10)]

print ShopCart(orders=orders_normal, customer=customer_zhang, promotion=GoodCustomerPromotion)
print ShopCart(orders=orders_normal, customer=customer_long, promotion=GoodCustomerPromotion)
print ShopCart(orders=orders_normal, customer=customer_william, promotion=GoodCustomerPromotion)
print ShopCart(orders=orders_sigleton, customer=customer_william, promotion=SigletonProductionPromotion)
print ShopCart(orders=orders_different, customer=customer_william, promotion=ManyDifferentProductionPromotion)

执行结果
在这里插入图片描述


3. 最佳的策略模式

然后在此基础上, 写一个最佳的策略模式

def best_promotion(shop_car):
	return max([promotion(shop_car) for promotion in [GoodCustomerPromotion, SigletonProductionPromotion, ManyDifferentProductionPromotion]])

print ShopCart(orders=orders_normal, customer=customer_william, promotion=best_promotion)

4. 全部策略

全部策略
实际上讲的使module内部外部得到module中的属性
先说在内部得到, 可使用globals()
globals, 代表的使当前的全局符号表
可以这样写

# 找出该模块中所有的策略
all_promos = [globals()[name] for name in globals().keys() if name.endswith('Promotion')]
print all_promos

当然, 在当前的module中当然不能使用globals()来获取别的module中的属性
可以使用inspect模块, 在同目录下创建一个新的文件

import inspect
import test
pomoros = [func_name for func_name, func in inspect.getmembers(old_test_01, inspect.isfunction) if func_name.endswith('Promotion')]
print pomoros

执行结果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40666620/article/details/112298368