策略模式

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化,即封装变化的算法。

策略模式的本质是将算法封装起来。下面看一个常见的代码

<?php
/**
 * @param string $driver
 * @param string $msg
 * @datetime 2020/7/17 5:42 PM
 * @author roach
 * @email jhq0113@163.com
 */
function log($driver, $msg) {
    switch ($driver) {
        case 'db':
            /**
             * @var \PDO $db
             */
            $stmt = $db->prepare('INSERT INTO `roach`(`msg`)VALUES(?)');
            $stmt->execute([ $msg ]);
        case 'redis':
            /**
             * @var \Redis $redis
             */
            $redis->lPush('roach:log', $msg);
        default:
            file_put_contents('/tmp/roach.log', $msg, FILE_APPEND| LOCK_EX);
    }
}

以上我们实现了记录日志的简单基本功能,调用端提供drivermsg参数即可,调用api很简单,log方法里的实现也就用了一个switch,这里有什么问题呢?

以上代码看着很简单,没什么大问题,但是我们考虑一下,是否对修改关闭了,当我们需要修改某一个driver记录日志的细节时,都需要修改log方法,可见没有对修改关闭;再看一下,如果我们需要增加kafka驱动,还是需要修改log方法,可见也不是对扩展开放,那么怎么修改呢?

这里就用到了策略模式,下面是应用策略模式实现一个打日志功能

<?php
/**
 * Class LogContext
 * @datetime 2020/7/17 5:51 PM
 * @author roach
 * @email jhq0113@163.com
 */
class LogContext
{
    /**
     * @var ILog
     * @datetime 2020/7/17 5:51 PM
     * @author roach
     * @email jhq0113@163.com 
     */
     private $_driver;

    /**
     * @param ILog $driver
     * @datetime 2020/7/17 5:51 PM
     * @author roach
     * @email jhq0113@163.com
     */
     public function setDriver(ILog $driver)
     {
         $this->_driver = $driver;
     }

    /**
     * @param $msg
     * @datetime 2020/7/17 5:52 PM
     * @author roach
     * @email jhq0113@163.com
     */
     public function log($msg)
     {
         $this->_driver->log($msg);
     }
}

/**
 * Interface ILog
 * @datetime 2020/7/17 5:50 PM
 * @author roach
 * @email jhq0113@163.com
 */
interface ILog
{
    /**
     * @param string $msg
     * @return mixed
     * @datetime 2020/7/17 5:50 PM
     * @author roach
     * @email jhq0113@163.com
     */
    public function log($msg);
}

/**
 * Class Redis
 * @datetime 2020/7/17 5:52 PM
 * @author roach
 * @email jhq0113@163.com
 */
class Redis implements ILog
{
    /**
     * @param string $msg
     * @return mixed|void
     * @datetime 2020/7/17 5:52 PM
     * @author roach
     * @email jhq0113@163.com
     */
    public function log($msg)
    {
        /**
         * @var \Redis $redis
         */
        $redis->lPush('roach:log', $msg);
    }
}

/**
 * Class File
 * @datetime 2020/7/17 5:53 PM
 * @author roach
 * @email jhq0113@163.com
 */
class File implements ILog
{
    /**
     * @param string $msg
     * @return mixed|void
     * @datetime 2020/7/17 5:53 PM
     * @author roach
     * @email jhq0113@163.com
     */
    public function log($msg)
    {
        file_put_contents('/tmp/roach.log', $msg, FILE_APPEND| LOCK_EX);
    }
}

/**
 * Class Db
 * @datetime 2020/7/17 5:54 PM
 * @author roach
 * @email jhq0113@163.com
 */
class Db implements ILog
{
    /**
     * @param string $msg
     * @return mixed|void
     * @datetime 2020/7/17 5:54 PM
     * @author roach
     * @email jhq0113@163.com
     */
    public function log($msg)
    {
        /**
         * @var \PDO $db
         */
        $stmt = $db->prepare('INSERT INTO `roach`(`msg`)VALUES(?)');
        $stmt->execute([ $msg ]);
    }
}

以上代码是一个策略模式的实现例程,调用端如果想记录日志,通过调用LogContextlog方法即可,在调用log方法前需要调用setDriver初始化_driver实例。现在我们再来看是否对修改关闭了,当我们想修改文件日志行为,直接修改类File即可,其他的driver不受影响;再看是否对扩展开放,当我们想把日志记录到Kafka里,我们增加Kafka类即可,其他driver不受影响。

关于策略模式,你学会了吗?

学习更多内容: https://404.360tryst.com

我的视频课程: https://edu.csdn.net/course/detail/9933

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苍穹0113

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值