概念解析
策略模式,在于将每个算法都封装起来,并且使它们之间可以相互替换,策略模式可以使算法可以独立使用它的用户而发生变化。其设计模式中的三个角色在于:
- 上下文环境(Context):起着承上启下的封装作用,屏蔽上层应用对策略(算法)的直接访问,封装可能存在的变化
- 策略的抽象(Strategy):策略(算法)的抽象类,定义统一 的接口,规定每个子类型需要实现的方法
- 具备的策略:策略的具体实现者,可以有多个不同的算法以及规则实现
策略模式类图如下:
策略模式的优点:
- 算法/规则可以自由切换
- 避免使用多重条件进行判断
- 方便拓展和增加新的算法(规则)
缺点:
- 所有策略类都需要对外暴露
可适用的场景:
- 系统中存在很多类,之间的区别在于其不同的行为/策略,则可以采用策略模式动态地让一个对象在许多行为中进行选择
- 设计程序接口时,希望部分内部实现由调用方自己实现
实例分析
基于策略模式简单设计一个比较器:输入为不同人(Person类),具备不同的特性:身高/体重等,需要设计不同的比较器,进行不同维度上的比较(Python层面其实可以基于内置sorted函数实现) 以下提供泛化层面的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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 show_myself(self):
print("%s 年龄:%d 岁,体重:%0.2f kg,身高: %0.2f m" % (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(IComparable):
"""通过身高排序"""
def comparable(self, person1, person2):
return person1.height - person2.height
class SortPerson():
"""Person的排序类"""
def __init__(self, compare):
self.__compare = compare
def sort(self, person_list):
"""排序算法
这里采用最采用的冒泡排序"""
n = len(person_list)
for i in range(0, n-1):
for j in range(0, n-i-1):
if self.__compare.comparable(person_list[j], person_list[j+1]) > 0:
tmp = person_list[j]
person_list[j] = person_list[j + 1]
person_list[j + 1] = tmp