什么是策略模式?
策略模式是一种对象行为型设计模式,它允许在运行时选择算法行为,将其封装在单独的类型中,然后在程序中使用该类型的实例来代替实际并发算法的实现。
模式的动机是什么?
让我们看一下将一组特定算法编程到类中的一些问题:
interface SortingAlgorithm {
public function sort(array $numbers): array;
}
class BubbleSort implements SortingAlgorithm {
public function sort(array $numbers): array
{
// 定义冒泡算法
return $numbers;
}
}
class QuickSort implements SortingAlgorithm {
public function sort(array $numbers): array
{
// 定义快排算法
return $numbers;
}
}
class SortableArray {
private $numbers;
private $algorithm;
public function __construct(array $numbers, SortingAlgorithm $algorithm)
{
$this->numbers = $numbers;
$this->algorithm = $algorithm;
}
public function sort(): array
{
return $this->algorithm->sort($this->numbers);
}
}
我们可以看到,这个实现中有很多问题:
- 高层类想要了解低层类的算法细节,这会导致高层类的复杂性大大增加;
- 各个算法之间的耦合度很高,这意味着每次添加新算法时都需要对应更改现有算法代码;
- 在不存在默认算法的情况下,高层组件必须要知道所需算法的类名,这将使其极其难以维护。
策略模式适用于哪些场景?
策略模式适用于以下场景:
- 一个程序中包含有适用于某种特定情况下的算法集合,程序需要根据具体情况动态地选用其中一种算法;
- 不同的算法之间可以相互替换;
- 程序需要支持多种算法,并且需要在运行时动态地切换算法;
- 一个算法的不同实现方式之间的区别仅在于使用的数据结构或者使用的基本算法;
- 需要封装算法中不能公开的数据以及设计模式中的其他可变部分;
- 使用条件语句展示多种算法将会导致复杂的代码。
策略模式的结构是什么?
策略模式由三个部分组成:
- Context(环境): 定义策略模式中的共有代码,同时该环境会持有一个对于策略模式中所有的具体策略对象的引用。这个环境类会将客户端所请求的具体策略定义为一个接口来实现,在这个接口中调用实际运行时所需的策略对象。
- Strategy(策略): 策略是策略模式的实际干活者,它在 Context 对象调用其算法之前进行具体策略的实现。
- ConcreteStrategy(具体策略): 具体策略只是策略的实现,它负责实现 Context 类定义的接口。
策略模式的优缺点是什么?
策略模式的优点:
- 通过将算法的实现封装到交互中,将它们从高层次的模块中分离;
- 策略类可以独立于其他类进行测试;
- 犯错的概率较小。
策略模式的缺点:
- 它增加了对象的数量;
- 要使用策略模式,必须了解数据类型和算法的使用方法;
- 它增加了系统的复杂性。
策略模式的实例展示
下面展示了在 PHP 中使用策略模式排序算法的实例,该实例仅包含核心代码:
interface SortingAlgorithm {
public function doSort(array $data);
}
class BubbleSort implements SortingAlgorithm {
public function doSort(array $data)
{
// 冒泡排序算法
return $data;
}
}
class InsertionSort implements SortingAlgorithm {
public function doSort(array $data)
{
// 插入排序算法
return $data;
}
}
class SortingContext {
private $algorithm;
public function setAlgorithm(SortingAlgorithm $algorithm)
{
$this->algorithm = $algorithm;
}
public function sortData(array $data)
{
return $this->algorithm->doSort($data);
}
}
在这个例子中,SortingContext 就是环境,SortingAlgorithm 就是策略,BubbleSort 和 InsertionSort 就是具体策略。
总结
策略模式是解决不同算法之间的复杂耦合问题的重要工具。将算法实现在具体策略中,而非高层调用代码中,可以保证程序的灵活性和可维护性。