• 设计模式 行为型


    策略模式(Strategy)

    意图

    对象有某个行为,但是在 不同的场景 下,该行为有 不同的实现算法

    就好比你去餐馆吃饭,首页你要通过菜单来选择你想吃的菜,根据你点的菜的不同,在厨房中去做不同的菜。同样是菜但是根据不同的菜名,有不同的做法。

    适用性

    • 需要在不同的情况下使用不同的策略(算法),或者在未来可能还要使用新的策略
    • 对客户隐藏具体策略(算法)的具体的实现,彼此完全独立

    实现方式

    1. 定义抽象策略类,通常由一个接口或抽象类实现。
    2. 具体策略类,封装了具体的算法和行为。
    3. 环境类,持有一个策略类的引用,最终给客户端调用。

    缺点

    1. 客户端 必须知道所有的策略类 ,并自行选择使用哪一个策略类。
    2. 策略模式造成很多的策略类,每个具体策略类都会产生一个新类 【可使用「享元模式」来减少对象的数量】

    代码示例

    支付方式

    这里以 支付 为例,
    我们在购买商品时,经常会选择不同支付方式来付款,这就是一种策略。

    UML类图

    image-20191112223237186

    抽象策略类

    PayStrategy.php

    <?php
    /**
     * Description: 支付策略 抽象接口类
     * Created by Martini
     * DateTime: 2019-07-02 13:39
     */
    
    namespace DesignPatternsBehavioralStrategy;
    
    interface PayStrategy
    {
        /**
         * 支付算法
         * @return mixed
         * @author Martini 2019-07-02 14:15
         */
        public function payAlgorithm();
    }
    

    具体策略类

    Alipay.php

    <?php
    /**
     * Description:[具体策略类(ConcreteStrategy)] 支付宝支付类
     * Created by Martini
     * DateTime: 2019-07-02 13:42
     */
    
    namespace DesignPatternsBehavioralStrategy;
    
    class Alipay implements PayStrategy
    {
        public function payAlgorithm()
        {
            return '使用支付宝支付相关支付算法';
        }
    }
    

    具体策略类

    Wechatpay.php

    <?php
    /**
     * Description: [具体策略类(ConcreteStrategy)] 微信支付类
     * Created by Martini
     * DateTime: 2019-07-02 13:44
     */
    
    namespace DesignPatternsBehavioralStrategy;
    
    class Wechatpay implements PayStrategy
    {
        public function payAlgorithm()
        {
            return '使用微信支付相关支付算法';
        }
    }
    

    环境类

    PayUtils.php

    <?php
    /**
     * Description:[环境类(Context)] 支付实用工具类
     * 用一个ConcreteStrategy具体策略类对象来配置
     * 维护一个对Strategy策略对象的引用. 可以定义一个接口来让Strategy访问它的数据
     * Created by Martini
     * DateTime: 2019-07-02 13:49
     */
    
    namespace DesignPatternsBehavioralStrategy;
    
    class PayUtils
    {
        private $_strategy = null;
    
        public function __construct(PayStrategy $pay)
        {
            $this->_strategy = $pay;
        }
    
        /**
         * 更改支付策略
         * @param PayStrategy $pay
         *
         * @author Martini 2019-07-02 14:01
         */
        public function setPayStrategy(PayStrategy $pay)
        {
            $this->_strategy = $pay;
        }
    
        /**
         * 支付
         * @return mixed
         * @author Martini 2019-07-02 14:02
         */
        public function pay()
        {
            return $this->_strategy->payAlgorithm();
        }
    }
    

    测试

    <?php
    /**
     * Description: 策略模式测试 支付策略测试用例
     * Created by Martini
     * DateTime: 2019-07-02 14:07
     */
    
    namespace DesignPatternsBehavioralStrategyTests;
    
    use DesignPatternsBehavioralStrategyAlipay;
    use DesignPatternsBehavioralStrategyPayUtils;
    use DesignPatternsBehavioralStrategyWechatpay;
    use PHPUnitFrameworkTestCase;
    
    class StrategyTest extends TestCase
    {
        public function testPay()
        {
            // 使用支付宝支付
            $pay = new PayUtils(new Alipay());
            $this->assertEquals('使用支付宝支付相关支付算法', $pay->pay());
    
            //切换为使用微信支付
            $pay->setPayStrategy(new Wechatpay());
            $this->assertEquals('使用微信支付相关支付算法', $pay->pay());
        }
    }
    
  • 相关阅读:
    springboot配置springbatch+mybatisplus对mybatis sqlsessionfactory的配置
    bytes的hex和fromhex函数
    python 锁 装饰器
    socket 客户端和服务端
    socket 客户端和服务端思考
    socket 发送类
    socket 服务端
    OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。
    for循环执行顺序流程
    Chromedriver的安装教程
  • 原文地址:https://www.cnblogs.com/martini-d/p/Strategy.html
Copyright © 2020-2023  润新知