• 技术文章 >后端开发 >php教程

    浅谈PHP中的责任链模式

    青灯夜游青灯夜游2021-07-12 20:00:45转载567
    在之前的文章《一起聊聊PHP中的策略模式》中我们介绍了PHP中的策略模式,下面本篇文章带大家了解一下PHP中的责任链模式。

    责任链模式,属于对象行为型的设计模式。

    Gof类图及解释

    GoF定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

    GoF类图:

    1.jpg

    代码实现

    abstract class Handler
    {
        protected $successor;
        public function setSuccessor($successor)
        {
            $this->successor = $successor;
        }
        abstract public function HandleRequst($request);
    }

    定义抽象责任链类,使用$successor保存后继链条。

    class ConcreteHandler1 extends Handler
    {
        public function HandleRequst($request)
        {
            if (is_numeric($request)) {
                return '请求参数是数字:' . $request;
            } else {
                return $this->successor->HandleRequst($request);
            }
        }
    }
    
    class ConcreteHandler2 extends Handler
    {
        public function HandleRequst($request)
        {
            if (is_string($request)) {
                return '请求参数是字符串:' . $request;
            } else {
                return $this->successor->HandleRequst($request);
            }
        }
    }
    
    class ConcreteHandler3 extends Handler
    {
        public function HandleRequst($request)
        {
            return '我也不知道请求参数是啥了,你猜猜?' . gettype($request);
        }
    }

    三个责任链条的具体实现,主要功能是判断传入的数据类型,如果是数字由第一个类处理,如果是字符串,则第二个类处理。如果是其他类型,第三个类统一处理。

    $handle1 = new ConcreteHandler1();
    $handle2 = new ConcreteHandler2();
    $handle3 = new ConcreteHandler3();
    
    $handle1->setSuccessor($handle2);
    $handle2->setSuccessor($handle3);
    
    $requests = [22, 'aaa', 55, 'cc', [1, 2, 3], null, new stdClass];
    
    foreach ($requests as $request) {
        echo $handle1->HandleRequst($request) . PHP_EOL;
    }

    客户端的调用,依次实例化三个责任链实例,并指定链条成员。创建请求参数,之后通过责任链来进行结果判断。

    我们一直在说手机制造这个行业,之前我们一直是交给代工厂来进行手机的组装生产,这回,我们自己建立了一条流水线。而这个流水线,就非常像责任链模式,怎么说呢,从一台手机的装配说起。有操作员将手机主板(初始请求)放到流水线上,然后工人开始添加内存、CPU、摄像头(各种责任链条类进行处理),期间也会经过测试和调整以达到最佳出厂性能。最后拼装成一台完整的手机交到客户的手中,这种工作流是不是和责任链非常相似呢!!

    完整代码:https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain.php

    实例

    依然还是短信功能,但这次我们要实现的是一个短信内容过滤的子功能。大家都知道,我们对广告有着严格的规定,许多词都在广告法中被标记为禁止使用的词汇,更有些严重的词汇可能会引来不必要的麻烦。这时候,我们就需要一套过滤机制来进行词汇的过滤。针对不同类型的词汇,我们可以通过责任链来进行过滤,比如严重违法的词汇当然是这条信息都不能通过。一些比较严重但可以绕过的词,我们可以进行替换或者加星处理,这样,客户端不需要一大堆的if..else..来进行逻辑判断,使用责任链让他们一步步的进行审批就好啦!!

    短信发送类图

    2.jpg

    完整源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain-filter-message.php

    // 词汇过滤链条
    abstract class FilterChain
    {
        protected $next;
        public function setNext($next)
        {
            $this->next = $next;
        }
        abstract public function filter($message);
    }
    
    // 严禁词汇
    class FilterStrict extends FilterChain
    {
        public function filter($message)
        {
            foreach (['枪X', '弹X', '毒X'] as $v) {
                if (strpos($message, $v) !== false) {
                    throw new \Exception('该信息包含敏感词汇!');
                }
            }
            if ($this->next) {
                return $this->next->filter($message);
            } else {
                return $message;
            }
        }
    }
    
    // 警告词汇
    class FilterWarning extends FilterChain
    {
        public function filter($message)
        {
            $message = str_replace(['打架', '丰胸', '偷税'], '*', $message);
            if ($this->next) {
                return $this->next->filter($message);
            } else {
                return $message;
            }
        }
    }
    
    // 手机号加星
    class FilterMobile extends FilterChain
    {
        public function filter($message)
        {
            $message = preg_replace("/(1[3|5|7|8]\d)\d{4}(\d{4})/i", "$1****$2", $message);
            if ($this->next) {
                return $this->next->filter($message);
            } else {
                return $message;
            }
        }
    }
    
    $f1 = new FilterStrict();
    $f2 = new FilterWarning();
    $f3 = new FilterMobile();
    
    $f1->setNext($f2);
    $f2->setNext($f3);
    
    $m1 = "现在开始测试链条1:语句中不包含敏感词,需要替换掉打架这种词,然后给手机号加上星:13333333333,这样的数据才可以对外展示哦";
    echo $f1->filter($m1);
    echo PHP_EOL;
    
    $m2 = "现在开始测试链条2:这条语句走不到后面,因为包含了毒X,直接就报错了!!!语句中不包含敏感词,需要替换掉打架这种词,然后给手机号加上星:13333333333,这样的数据才可以对外展示哦";
    echo $f1->filter($m2);
    echo PHP_EOL;

    说明

    原文地址:https://juejin.cn/post/6844903957974908942

    作者:硬核项目经理

    推荐学习:《PHP视频教程

    以上就是浅谈PHP中的责任链模式的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    上一篇:php如何计算字符串长度?两种方法对比 下一篇:带大家学习PHP中的文件系统函数(一)
    VIP会员

    相关文章推荐

    • PHP数组学习之巧用函数插入元素(二)• PHP数组学习之巧用函数插入元素(一)• PHP自定义显示Floyd三角形的前几行• 深入浅析PHP中的访问者模式• 通过PHP正则表达式去除az AZ 0-9或空之外的所有字符

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网