【设计模式】策略模式

一、介绍

策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换。

这里列举两个例子来说明下策略模式的使用场景:

(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);
    }
}
相关推荐
智能直播8 小时前
网络RTMP拉流不卡顿、声音不同步,一文讲透缓冲区、时间戳
开发语言·ffmpeg·php·音视频·视频编解码
墨云安全9 小时前
内网资产无法暴露到公网,怎么做安全检测?2026 年内网渗透测试的落地路径
开发语言·安全·网络安全·渗透测试·php
我是唐青枫11 小时前
Yii2 Applications 详解:应用生命周期、组件配置与多入口实战
php
kimnoic12 小时前
PHP 8.2的DNF类型怎么用才规范
开发语言·php
中屹指纹浏览器svip13 小时前
打开账号环境网页报错,常见原因有哪些?
服务器·开发语言·php·中屹指纹浏览器
希洛兔15 小时前
状态模式详解:让对象随内部状态自动改变行为
java·设计模式·状态模式
修船大队长15 小时前
CanNm 从休眠唤醒后重复消息报文的周期与数量分析
开发语言·php
李纲明16 小时前
WordPress 安全加固基线:更新策略、文件权限、登录面收缩和备份验证(含回滚注意)
运维·安全·php·wordpress
Novproxy_Z16 小时前
IPv4 与 IPv6 代理在跨境自动化场景下的选型与风险
运维·自动化·php
kimnoic17 小时前
PHP 8.3 数据库备份失败怎么排查
开发语言·php