若转载教程,请注明出自SW-X框架官方文档
<?php
/**
* 设计模式之策略模式
* 优势在 根据类名调用不同的算法
* 小黄牛
*/
header("Content-type: text/html; charset=utf-8");
/**
* 抽象策略类
* 派生出相关的算法和行为
*/
abstract class RotateItem {
# 暂定2个
public abstract function Algorithm();
public abstract function Behavior();
}
/**
* 策略角色类 - 算法1
*/
class AItem extends RotateItem{
public function Algorithm(){
echo '算法1:我爱计算,头脑好好!<br/>';
}
function Behavior(){
echo '算法1:我爱洗澡,皮肤好好!<br/>';
}
}
/**
* 策略角色类 - 算法2
*/
class BItem extends RotateItem{
public function Algorithm(){
echo '算法2:我爱计算,头脑好好!<br/>';
}
function Behavior(){
echo '算法2:我爱洗澡,皮肤好好!<br/>';
}
}
/**
* 环境角色类 - 通过这个类调用对应的策略算法
*/
class ContextItem{
private $item; // 用户存储一个策略类的引用,最终返还给客户端调用。
public function getItem($item_name, $fun_name){
# 1、通过系统 ReflectionClass方法获得类的各项参数
$class = new ReflectionClass($item_name);
# 2、再通过系统 newInstance方法实例化一个类
$this->item = $class->newInstance();
# 3、根据方法名调用对应的算法或行为
$this->item->$fun_name();
}
}
# 实例DEMO
$obj = new ContextItem();
$obj->getItem('BItem','Algorithm');
$obj->getItem('AItem','Behavior');
浏览器输出
算法2:我爱计算,头脑好好!
算法1:我爱洗澡,皮肤好好!
策略模式
抽象策略角色(RotateItem):策略类,通常由一个接口或者抽象类实现。
具体策略角色(ItemX):包装了相关的算法和行为。
环境角色(ItemContext):持有一个策略类的引用,最终给客户端调用。
应用场景
1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
3、 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。
4、客户端必须知道所有的策略类,并自行决定使用哪一个策略类,策略模式只适用于客户端知道所有的算法或行为的情况。
5、 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。
优点
1、当你知道所有算法名的时候,策略模式可以很好的区分逻辑与行为,并通过统一的应用入口进行生产调用。
2、使用策略模式可以避免使用多重条件转移语句。
多重转移语句(switch / if)不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
缺点
1、使用者必须知道所有的策略类,并自行决定使用哪一个策略类。
这就意味着使用者必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于用户群知道所有的算法或行为的情况。
2、 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。
有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。