【python】简单工厂模式
【python】策略模式
抽空学习下常见的20几种设计模式,python2.7来设计实现。基本就根据某设计模式书籍来实现python版本。希望能坚持下来全部介绍完。设计模式介绍中可能会涉及到一些UML类图,忘了的可以看一下https://blog.csdn.net/zhaxun/article/details/124048871
策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。
策略模式:
定义了一组算法(业务规则);
封装了每个算法;
这族的算法可互换代替(interchangeable)。
策略模式就是用来封装算法的,就像待会举例的get_result(),把不同策略的算法统一起来。
优点
1、 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码。
2、 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
3、 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
缺点
1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
2、 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。
学习了简单工厂模式以后 我们先来简单复习一下。
商场需要一个收银软件,营业员根据不同折扣模式来进行收费,例如有正常收费,打折收费,满减收费三种,请利用简单工厂模式设计实现。
代码如下:
# encoding: utf-8
import math
# 现金收费基类
class CashSuper(object):
def accept_cash(self, money):
raise NotImplementedError
# 正常收费子类
class CashNormal(CashSuper):
def accept_cash(self, money):
return money
# 打折收费子类
class CashRebate(CashSuper):
def __init__(self, rebate=1.0):
self._rebate = rebate
def accept_cash(self, money):
return money * self._rebate
# 返利收费子类
class CashReturn(CashSuper):
def __init__(self, condition=0, money_return=0):
self._condition = condition
self._return = money_return
def accept_cash(self, money):
result = money
if money >= self._condition:
result = money - math.floor(money / self._condition) * self._return
return result
# 现金收费工厂类
class CashFactory(object):
@staticmethod
def create_cash_accept(cash_type):
cash_type_instance = None
if cash_type == '正常收费':
cash_type_instance = CashNormal()
elif cash_type == '打8折':
cash_type_instance = CashRebate(0.8)
elif cash_type == '满300返100':
cash_type_instance = CashReturn(300, 100)
return cash_type_instance
if __name__ == '__main__':
print CashFactory.create_cash_accept('正常收费').accept_cash(400)
print CashFactory.create_cash_accept('打8折').accept_cash(400)
print CashFactory.create_cash_accept('满300返100').accept_cash(400)
代码如下:
# encoding: utf-8
import math
# 现金收费基类
class CashSuper(object):
def accept_cash(self, money):
raise NotImplementedError
# 正常收费子类
class CashNormal(CashSuper):
def accept_cash(self, money):
return money
# 打折收费子类
class CashRebate(CashSuper):
def __init__(self, rebate=1.0):
self._rebate = rebate
def accept_cash(self, money):
return money * self._rebate
# 返利收费子类
class CashReturn(CashSuper):
def __init__(self, condition=0, money_return=0):
self._condition = condition
self._return = money_return
def accept_cash(self, money):
result = money
if money >= self._condition:
result = money - math.floor(money / self._condition) * self._return
return result
# 上下文类,维护一个对收费模型的引用
class CashContext(object):
def __init__(self, cash_type_instance):
self.cash_type_instance = cash_type_instance
def get_result(self, money):
return self.cash_type_instance.accept_cash(money)
if __name__ == '__main__':
def init_cash_accept(cash_type):
cash_content = None
if cash_type == '正常收费':
cash_content = CashContext(CashNormal())
elif cash_type == '打8折':
cash_content = CashContext(CashRebate(0.8))
elif cash_type == '满300返100':
cash_content = CashContext(CashReturn(300, 100))
return cash_content
print init_cash_accept('正常收费').get_result(400)
print init_cash_accept('打8折').get_result(400)
print init_cash_accept('满300返100').get_result(400)
单纯用策略模式,客户端需要去判断具体选哪种算法,这里我们把策略模式和简单工厂相互结合一下。
代码如下:
# encoding: utf-8
import math
# 现金收费基类
class CashSuper(object):
def accept_cash(self, money):
raise NotImplementedError
# 正常收费子类
class CashNormal(CashSuper):
def accept_cash(self, money):
return money
# 打折收费子类
class CashRebate(CashSuper):
def __init__(self, rebate=1.0):
self._rebate = rebate
def accept_cash(self, money):
return money * self._rebate
# 返利收费子类
class CashReturn(CashSuper):
def __init__(self, condition=0, money_return=0):
self._condition = condition
self._return = money_return
def accept_cash(self, money):
result = money
if money >= self._condition:
result = money - math.floor(money / self._condition) * self._return
return result
# 上下文类,维护一个对收费模型的引用
class CashContext(object):
def __init__(self, cash_type):
self._cash_type = cash_type
self.cash_type_instance = None
self.init_cash_accept()
def init_cash_accept(self):
if self._cash_type == '正常收费':
self.cash_type_instance = CashNormal()
elif self._cash_type == '打8折':
self.cash_type_instance = CashRebate(0.8)
elif self._cash_type == '满300返100':
self.cash_type_instance = CashReturn(300, 100)
def get_result(self, money):
return self.cash_type_instance.accept_cash(money)
if __name__ == '__main__':
print CashContext('正常收费').get_result(400)
print CashContext('打8折').get_result(400)
print CashContext('满300返100').get_result(400)
简单工厂模式和策略模式的形式很像,对比一下上面两张UML类图可以知道,工厂Factory对CashSuper持有依赖关系,策略Context对CashSuper持有的是聚合关系。在对比客户端代码。简单工厂模式要让客户端认识CashFactory和CashSuper两个类,而策略模式只需要暴露给客户端CashContext一个类即可,客户端实例化CashContext对象,调用get_result方法,使得具体的收费算法彻底和客户端分离。
# 简单工厂
if __name__ == '__main__':
print CashFactory.create_cash_accept('正常收费').accept_cash(400)
print CashFactory.create_cash_accept('打8折').accept_cash(400)
print CashFactory.create_cash_accept('满300返100').accept_cash(400)
# 策略
if __name__ == '__main__':
print CashContext('正常收费').get_result(400)
print CashContext('打8折').get_result(400)
print CashContext('满300返100').get_result(400)
但是话说回来,在CashContext中,还是有需要if和else判断类型,增加策略,就得增加elif。或许会有什么更好的方法等着我们。听说反射技术是个不错的选择,等后续介绍吧。