定义
- 定义一系列算法,将每个算法都封装起来,并且使它们之间可以相互替换。策略模式使算法可以独立于使用它的用户而变化。
- 核心思想是:对算法、规则进行封装,使得替换算法和新增算法更加灵活。
策略模式的模型抽象
类图
模型说明
- 策略模式中主要有三个角色,在设计策略模式时要找到并区分这些角色。
- 上下文环境(Context):起着承上启下的封装作用,屏蔽上层应用对策略(算法)的直接访问,封装可能存在的变化。
- 策略的抽象(Strategy):策略(算法)的抽象类,定义统一的接口,规定每个子类必须实现的方法。
- 具备的策略:策略的具体实现者,可以有多个不同的(算法或规则)实现。
- 策略模式的优缺点
- 优点:
- 算法(规则)可自由切换。
- 避免使用多重条件判断。
- 方便拓展和增加新的算法(规则)。
- 缺点:
例子
from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
class Person:
"""人类"""
def __init__(self, name, age, weight, height):
self.name = name
self.age = age
self.weight = weight
self.height = height
def showMysef(self):
print("%s 年龄:%d岁,体重:%0.2fkg,身高:%0.2fm" % (self.name, self.age, self.weight, self.height))
class ICompare(metaclass=ABCMeta):
"""比较算法"""
@abstractmethod
def comparable(self, person1, person2):
"person1 > person2 返回值>0,person1 == person2 返回0, person1 < person2 返回值小于0"
pass
class CompareByAge(ICompare):
"""通过年龄排序"""
def comparable(self, person1, person2):
return person1.age - person2.age
class CompareByHeight(ICompare):
"""通过身高进行排序"""
def comparable(self, person1, person2):
return person1.height - person2.height
class CompareByHeightAndWeight(ICompare):
"""根据身高和体重的综合情况来排序
(身高和体重的权重分别是0.6和0.4)"""
def comparable(self, person1, person2):
value1 = person1.height * 0.6 + person1.weight * 0.4
value2 = person2.height * 0.6 + person2.weight * 0.4
return value1 - value2
class SortPerson:
"""Person的排序类"""
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:
tmp = personList[j]
personList[j] = personList[j + 1]
personList[j + 1] = tmp
j += 1
i += 1
def testSortPerson():
personList = [
Person("Tony", 2, 54.5, 0.82),
Person("Jack", 31, 74.5, 1.80),
Person("Nick", 54, 44.5, 1.59),
Person("Eric", 23, 62.0, 1.78),
Person("Helen", 16, 45.7, 1.60)
]
ageSorter = SortPerson(CompareByAge())
ageSorter.sort(personList)
print("根据年龄进行排序后的结果:")
for person in personList:
person.showMysef()
print()
heightSorter = SortPerson(CompareByHeight())
heightSorter.sort(personList)
print("根据身高进行排序后的结果:")
for person in personList:
person.showMysef()
print()
testSortPerson()
引用场景
- 如果一个系统里面有许多类,它们之间的区别仅在于有不同的行为,那么可以使用策略模式动态地让一个对象在许多行为中选择一种。
- 一个系统需要动态地在几种算法中选择一种。
- 设计程序接口时希望部分内部实现由调用方自己实现。