策略模式
什么是策略模式?
定义一系列算法,将每个算法都封装起来,并且使它们之间可以相互替换。策略模式使算法可以独立于使用它的用户而变化。
策略模式的核心思想是:对算法、规则进行封装,使得替换算法和新增算法更加灵活。
策略模式的模型抽象
Context是一个上下文环境类,负责提供对外的接口,与用户交互,屏蔽上层对策略(算法)的直接访问,
Strategy是策略(算法)的抽象类,定义统一的接口,如故事剧情中的 IVehicle。
StrategyA 和 StrategyB 是具体策略的实现类
当策略比较简单,比如只实现一个方法且没有太多类属性需要维护时,在python中可以使用函数式编程的方法,实现策略模式。
实战场景一:
一群人采用不同交通方式到达聚会地点。
from abc import ABCMeta,abstractmethod
#abc中 ABCmeta负责python中构建抽象基类,abstractmethod负责定义抽象方法。
class Vehicle(metaclass=ABCMeta):
"""交通工具的抽象类"""
@abstractmethod
def running(self):
#定义抽象方法
pass
#定义抽象类和方法的,是为了:
#显性的表明这是策略设计模式
#为了为不同策略定制相同的接口API
class Bicycle(Vehicle):
"""自行车"""
def running(self):
print("骑共享单车",end="")
class Bus(Vehicle):
"""公交车"""
def running(self):
print("乘公交车",end="")
class Subway(Vehicle):
"""自行车"""
def running(self):
print("搭地铁",end="")
class Classmate:
"""聚餐同学"""
def __init__(self,name,vechicle):
self._name=name
self._vechicle=vechicle
def attendTheDinner(self):
print(self._name+" ",end="")
self._vechicle.running()
print("来聚餐")
def testTheDinner():
bicycle=Bicycle()
subway=Subway()
bus=Bus()
#创建交通策略实例
joe=Classmate("joe",bicycle)
joe.attendTheDinner()
uni=Classmate("uni",subway)
uni.attendTheDinner()
xiao=Classmate("xiao",bus)
xiao.attendTheDinner()
#三个小伙伴,都实现了聚餐这一目的,但是分别采用了不同的策略。
#用户和策略解耦,不同用户可以使用不同策略,同一用户也可是使用不同策略。
testTheDinner()
实现场景二:按照不同条件对人的类进行排序,例如身高,体重,更复杂的条件等。
from abc import ABCMeta,abstractmethod
class Person:
'''人类'''
def __init__(self,name,age,weight,height):
self.name=name
self.age=age
self.weight=weight
self.height=height
def showMyself(self):
print("%s 年龄:%d 岁,体重:%0.2fkg,身高:%0.2fm"%(self.name,self.age,
self.weight,self.height))
class Compare(metaclass=ABCMeta):
'''比较算法的抽象基类'''
@abstractmethod
def Comparable(self,person1,person2):
'''1>2 返回值>0. 1==2,返回值等于0,1<2 返回值<0'''
pass
class CompareByage(Compare):
'''通过年龄排序'''
def Comparable(self,person1,person2):
return person1.age-person2.age
class CompareByHight(Compare):
def Comparable(self,person1,person2):
return person1.height-person2.height
class SortPerson:
'''排序类'''
def __init__(self,compare):
self._compare=compare
#关键是这里,可以选择不同的排序策略
def sort(self,personList):
'''冒泡排序'''
n=len(personList)
for i in range(0,n-1):
for j in range(0,n-i-1):
if(self._compare.Comparable(personList[j],personList[j+1])>0):
temp=personList[j]
personList[j]=personList[j+1]
personList[j+1]=temp
j+=1
i+=1
def testSortPerson():
personList=[
Person("tony",2,54.5,0.82),
Person("uni",1,1,0.1),
Person("xiao",29,80,1.83)
]
ageSorter=SortPerson(CompareByage())
ageSorter.sort(personList)
for person in personList:
person.showMyself()
testSortPerson()
问题?python可以用简单的sorted()函数同样实现上述功能
#使用python的内置方法排序
from operator import itemgetter,attrgetter
personList=[
Person("tony",2,54.5,0.82),
Person("uni",1,1,0.1),
Person("xiao",29,80,1.83)
]
sort_person=sorted(personList,key=attrgetter(height))
for person in sort_person:
person.showMyself()
那么还有必要采用策略模式吗?
在简单的排序条件中,可以使用python函数,
但是python作为一种动态的编程语言,具备的便利特性在其他编程语言中,可能并不存在。
所以:
理解策略模式,还是必要的
当排序条件复杂时,sorted()函数并不能满足条件,此时仍然需要策略模式。
python中用函数式编程的方式,来实现场景二中的策略模式
pass