设计模式-策略模式
0x00 策略模式
策略模式,也叫政策模式, 使用的是面向对象的继承和多态机制。
定义
** Define a amily of algorithms, encapsulate each one, and make them interchangeable**. (定义一组算法,将每个算法都封装起来,并且使它们之间可以交换。)
三个角色组成
Context 封装角色, 也称上下文角色,起承上启下封装作用,屏蔽高层模块对策略,算法的直接访问,封装可能存在的变化。
Strategy 抽象策略角色,策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
ConcreteStrategy 具体策略角色,实现抽象策略中的操作,该类含有具体的算法。
优点
算法可以自由切换
只要实现了抽象策略,就成为了策略家族的一个成员,通过封装角色对其进行封装,保证对外提供“可自由切换”的策略。
避免使用多重条件判断
策略家族对外提供的访问接口就是封装类,简化操作,避免条件语句判断。
易于扩展
缺点
策略类数量增多
每个策略都是一个类,复用的可能性很小,类数量持续增多。
所有的策略类都需要对外暴露
上层模块必须知道有哪些策略,才能进一步决定使用哪一个策略。
使用场景
多个类只有算法或行为上略有不同的场景。
算法需要自由切换的场景。
需要屏蔽算法规则的场景。
PHP 实现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
51
<?php
// 抽象策略接口
interface Strategy {
public function doSth();
}
// 具体策略角色
class ConcreteStrategy1 implements Strategy {
public function doSth()
{
echo ‘strategy 1’;
}
}
class ConcreteStrategy2 implements Strategy {
public function doSth()
{
echo ‘strategy 2’;
}
}
// 封装角色
class Context {
private $strategy = null;
public function Context(Strategy $_strategy)
{
$this->strategy = $_strategy;
}
public function doAct()
{
$this->strategy->doSth();
}
}
// 场景类
class Client {
public static function main()
{
$strategy = new ConcreteStrategy1();
$context = new Context($strategy);
$context->doAct();
}
}
//调用
(new Client())::main(); // output: strategy 1