一、介绍
策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换。
这里列举两个例子来说明下策略模式的使用场景:
(1)根据会员等级来计算折扣力度。不同等级拥有不同的折扣力度,这样就可以根据策略模式去灵活的计算,就算之后又新增了几个等级的会员,也不用修改原代码,只需新增对应会员的具体策略就可以了。
(2)电子商务平台的支付,可以根据用户的选择来使用不同的支付策略(支付宝、银行卡、微信)。同理,之后新增其他支付类型时也只需要新增具体策略无需修改原代码。
二、优缺点:
优点:
- 可以将代码的实现和使用分离开来,增加了灵活性
- 符合开闭原则,无需对上下文进行修改就能够引入新的策略。
- 客户端代码可以根据需要在运行时切换策略,无需修改现有代码。
缺点:
- 如果具体的策略类过多会导致类的数量增加,进而维护成本增加。
- 客户端必须知晓各策略间的不同才能选择合适的策略。
三、核心结构
1、上下文(Context):上下文类负责维护对策略对象的引用,并在运行时切换策略。上下文类通常具有一个方法,用于执行当前策略。
2、策略接口(Strategy):通常由一个接口或抽象类实现,定义了具体策略类所需的接口。
3、具体策略类(Concrete Strategy):实现了上下文所用算法的各种不同变体。
四、代码实现
1、上下文(Context):上下文类负责维护对策略对象的引用,并在运行时切换策略。上下文类通常具有一个方法,用于执行当前策略。
<?php
/**
* Created by PhpStorm
* Author: fengzi
* Date: 2024/4/7
*/
namespace app\admin\service\strategy;
/**
* 策略模式的上下文
*/
class Context
{
private Strategy $strategy;
/**
* 构造函数
* Context constructor.
* @param Strategy $strategy
*/
public function __construct(Strategy $strategy)
{
$this->strategy = $strategy;
}
/**
* 设置策略对象
* @param Strategy $strategy
* @author fengzi
* @date 2023-05-23 17:02
*/
public function setStrategy(Strategy $strategy)
{
$this->strategy = $strategy;
}
/**
* 委托策略对象实现具体操作
* @param array $params
* @return mixed
* @author fengzi
* @date 2023-05-23 17:06
*/
public function doSomeLogic(array $params=[])
{
return $this->strategy->doAlgorithm($params);
}
}
2、策略接口(Strategy):通常由一个接口或抽象类实现,定义了具体策略类所需的接口。
<?php
/**
* Created by PhpStorm
* Author: fengzi
* Date: 2024/4/7
*/
namespace app\admin\service\strategy;
/**
* 策略接口
*/
interface Strategy
{
/**
* 实际计算的方法
* @param array $params
* @author fengzi
* @date 2023-05-24 16:47
*/
public function doAlgorithm(array $params=[]);
}
3、具体策略类(Concrete Strategy):实现了上下文所用算法的各种不同变体。
<?php
/**
* Created by PhpStorm
* Author: fengzi
* Date: 2024/4/7
*/
namespace app\admin\service\strategy;
/**
* 支付宝支付的具体策略
*/
class AlipayStrategy implements Strategy
{
public function doAlgorithm(array $params = [])
{
// TODO: Implement doAlgorithm() method.
echo '支付宝支付'.$params['price'].'元';
}
}
<?php
/**
* Created by PhpStorm
* Author: fengzi
* Date: 2024/4/7
*/
namespace app\admin\service\strategy;
/**
* 微信支付的具体策略
*/
class WeChatPayStrategy implements Strategy
{
public function doAlgorithm(array $params = [])
{
// TODO: Implement doAlgorithm() method.
echo '微信支付'.$params['price'].'元';
}
}
4、客户端调用及结果展示
<?php
/**
* Created by PhpStorm
* Author: fengzi
* Date: 2024/4/7
*/
namespace app\admin\controller\strategy;
use app\admin\service\strategy\AlipayStrategy;
use app\admin\service\strategy\Context;
use app\admin\service\strategy\WeChatPayStrategy;
/**
* 策略模式
*/
class StrategyController
{
/**
* 客户端使用策略模式
* @return void
* @Author: fengzi
* @Date: 2024/4/7
*/
public function index()
{
$date = [
'price' => 100.00,
];
$context = new Context(new AlipayStrategy());
$context->doSomeLogic($date);
echo PHP_EOL;
$context->setStrategy(new WeChatPayStrategy());
$context->doSomeLogic($date);
}
}