策略模式:定义一系列的算法,将算法进行封装,他们之间可以相互替换,让算法独立于使用他的角色而变化。
他是一种对象行为性模式。
完成一项任务,可以有不同的实现方式,每一种都是一种策略,在开发中有许多都会用到这种模式,例如:多种查找;我们可以将查找算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法。其实在开发中我们也可以通过if...else...来判断具体做哪种查找,但是如果我们后面增加或者修改了查找,不仅要修改if中的代码,客户端也必须同时修改,这样修改起来就比较麻烦,难维护。
在策略中我们定义一下几个角色:
1.抽象策略角色:策略类,通常由一个接口或者抽象类实现。
2.具体策略角色:包装了相关的算法和行为。
3.环境角色:持有一个策略类的引用,最终给客户端调用。
UML图:
st=>operation: Context +algorithm() +setStrategy(Strategy*)
e=>operation: strategy->algorithm();
op1=>operation: Strategy +algorithm()
op2=>operation: ConcreteStrategyA or ConcrenteStrategyB
cond=>condition: SelectStrategy
op2->op1->st(right)->e
简单实现:
1.定义抽象接口类
abstract class Strategy
{
abstract function selectAdvert();
}
2.具体的策略角色
//这里定义了两个策略角色
class ManStrategy extends Strategy
{
function selectAdvert(){
echo "男士广告展示";
}
}
class WomanStrategy extends Strategy
{
function selectAdvert(){
echo "女士广告展示";
}
}
3.环境角色
//环境角色
class Context
{
private $strategy;
//获取具体策略
function getStrategy($strategyName){
try{
$strategyReflection = new ReflectionClass($strategyName);
$this->strategy = $strategyReflection->newInstance();
}catch(ReflectionException $e){
$this->strategy = "";
}
}
function getAdvert(){
$this->strategy->selectAdvert();
}
}
4.客户端调用
$context = new Context();
$context->getStrategy("WomanStrategy");
$context->getAdvert();
模式的缺点:
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2.策略模式造成很多的策略类,每个具体策略类都会产生一个新类。