策略模式
策略模式定义一系列算法,将每个算法封装起来,并让他们可以相互替换.策略模式让算法独立于使用它的客户而变化.
存在很多算法相似的情况下,使用if...else这些分支语句,才能实现需求,但是不足之处在于一旦需要增加条件,那么所有用到这些分支的地方都需要修改,使用策略模式需要增加新的策略只需再增加一个具体策略类
目录结构
|strategy #项目根目录
|--Think #核心类库
|----Loder.php #自动加载类
|----context.php #环境类
|----manStrategy.php #男性用户策略
|----womanStrategy.php #女性用户策略
|----main #核心类
|------strategy.php #抽象策略接口
|--index.php #单一的入口文件
代码实例
抽象策略接口 Think/main/strategy.php
<?php
/**
* 抽象策略接口
*/
namespace Think\main;
abstract class strategy{
abstract function paddle();
}
男性用户策略 Think/manStrategy.php
<?php
/**
* 男性用户策略
*/
namespace Think;
use Think\main\strategy;
class manStrategy extends strategy{
public function paddle() {
echo '这里是男性用户策略'.PHP_EOL;
}
}
女性用户策略 Think/womanStrategy.php
<?php
/**
* 女性用户策略
*/
namespace Think;
use Think\main\strategy;
class womanStrategy extends strategy{
public function paddle() {
echo '这里是女性用户策略'.PHP_EOL;
}
}
环境类 Think/context.php
<?php
/**
* 环境类
*/
namespace Think;
class context{
protected $stratgy;
public function __construct($sex) {
if($sex == 'man'){
$strategy = new manStrategy();
}else{
$strategy = new womanStrategy();
}
$this->stratgy = $strategy;
}
public function request() {
$this->stratgy->paddle();
}
}
自动加载 Think/Loder.php
<?php
namespace Think;
class Loder{
static function autoload($class){
require BASEDIR . '/' .str_replace('\\','/',$class) . '.php';
}
}
入口文件 index.php
<?php
define('BASEDIR',__DIR__);
include BASEDIR . '/Think/Loder.php';
spl_autoload_register('\\Think\\Loder::autoload');
//假设用户性别为男性
$sex = 'man';
//使用策略模式
$context = new \Think\context($sex);
$context->request();
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
上一篇 php设计模式之适配器模式
下一篇 php设计模式之数据映射模式