思想:策略模式类似于模板方法模式,一个是静态控制,一个是动态控制。模板方法模式是将统一的方法在父类中实现,而将特殊的方法交给对应的子类实现,在子类中调用父类方法的同时也可直接使用子类自身已经实现的方法。策略模式是将可变的方法交给类 的外部指定函数来实现,在调用时直接调用该函数名称即可。下面的案例二和案例三分别是模板方法模式和策略模式,请仔细查看二者的区别。
意图:
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
适用性:
许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时 ,可以使用策略模式。
算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
案例一
class CashSuper:
def AcceptCash(self,money):
return 0
class CashNormal(CashSuper):
def AcceptCash(self,money):
return money
class CashRebate(CashSuper):
discount = 0
def __init__(self,ds):
self.discount = ds
def AcceptCash(self,money):
return money * self.discount
class CashReturn(CashSuper):
total = 0;
ret = 0;
def __init__(self,t,r):
self.total = t
self.ret = r
def AcceptCash(self,money):
if (money>=self.total):
return money - self.ret
else:
return money
class CashContext:
def __init__(self,csuper):
self.cs = csuper
def GetResult(self,money):
return self.cs.AcceptCash(money)
if __name__ == "__main__":
money = input("money:")
strategy = {}
strategy[1] = CashContext(CashNormal())
strategy[2] = CashContext(CashRebate(0.8))
strategy[3] = CashContext(CashReturn(300,100))
ctype = input("type:[1]for normal,[2]for 80% discount [3]for 300 -100.")
if ctype in strategy:
cc = strategy[ctype]
else:
print "Undefine type.Use normal mode."
cc = strategy[1]
print "you will pay:%d" %(cc.GetResult(money))
案例二:模板方法模式,以烹饪流程为例
class Dinner:
def buy(self):
print("买菜")
def wash(self):
pass
def cut(self):
pass
def fire(self):
print("炒菜")
# 流程回顾
def work(self):
self.buy()
self.wash()
self.cut()
self.fire()
# 定义一个烹饪实例
dinner=Dinner()
dinner.work()
# 运行结果:
# 买菜
# 炒菜
# 定义一个子类继承自烹饪类
class Dinner_child(Dinner):
def wash(self):
print("最新洗菜方式洗菜")
def cut(self):
print("最新切菜方法切菜")
dinner_child=Dinner_child()
dinner_child.work()
# 运行结果:
# 买菜
# 最新洗菜方式洗菜
# 最新切菜方法切菜
# 炒菜
模板方法模式:将统一的方法在父类中实现,可变的方法在子类中实现,子类依然可以通过父类的方法调用自己的方法。
案例三:将上述案例使用策略模式进行修改
class Dinner:
def buy(self):
print("买菜")
def wash(self):
pass
def cut(self):
pass
def fire(self):
print("炒菜")
# 将洗菜和切菜的方法通过函数名称传递
def work(self,wash,cut):
self.buy()
wash()
cut()
self.fire()
# 在类的外部,实现洗菜和切菜的方法
def wash():
print("最新洗菜方式洗菜")
def cut():
print("最新切菜方法切菜")
# 定义一个烹饪实例
dinner=Dinner()
dinner.work(wash,cut)
# 运行结果:
# 买菜
# 最新洗菜方式洗菜
# 最新切菜方法切菜
# 炒菜