陈大剩博客

php设计模式(十五):职责链模式(Chain of Responsibility)

  • 陈大剩
  • 2023-05-10 12:01:09
  • 722

责任链模式

责任链模式又称为:职责链模式、命令链、CoR、Chain of Command、Chain of Responsibility。责任链是一种行为设计模式,允许将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。

问题

假设我们需要开发一个线下“PHP设计模式”培训课,办一个班,需要政府审批。

所以我们去了当地县教育局,县教育局回复说:“你们这个是要开一个培训学校,我们这不管新开,你去市教育局看看”;理所当然我们到了市教育局,“啊,你们要开一个培训学校呀?这个我们没有这个权限,需要去省教育局”市教育局工作人员介绍到;我们又去了省教育局,这回没有走错了,“你把你们培训什么内容以及办学规模,填表就可以等结果了”省教育局工作人员介绍到。

这样我们可能会一个函数中,我们每次去一个地,我们都需要记录,而每次新增功能都会使其更加 臃肿(代码变得越来越多,也越来越混乱)。修改某个 审批步骤 有时会影响其他的 审批步骤。最糟糕的是,系统会变得让人非常费解,而且其维护成本也会激增。在艰难地和这些代码共处一段时间后,有一天终于决定对整个系统进行重构。

解决方法

在上述示例中我们要一级级去问,能不能使用一个统一方法,自动一级级去问,只到有地方可以答应为主,每个 审批步骤 都可被抽取为仅有单个方法的类,并执行检查操作。请求及其数据则会被作为参数传递给该方法。

将这些处理者连成一条链。链上的每个处理者都有一个成员变量来保存对于下一处理者的引用。除了处理请求外,处理者还负责沿着链传递请求。请求会在链上移动,直至所有处理者都有机会对其进行处理。

请求

处理者(教育局)接收到请求后自行决定是否能够对其进行处理。如果自己能够处理,处理者就不再继续传递请求。因此在这种情况下,每个请求要么最多有一个处理者对其进行处理,要么没有任何处理者对其进行处理。

结构

Handler:责任链接口基类;
BaseHandler :实现 Handler 接口的抽象责任链类(可有可无);
*EducationBureau:具体的责任链类 示例中指:县教育局、市教育局、省教育局;

代码示例

接口

interface Handler
{
    /**
     * 下一个请求
     * @return mixed
     * @author chendashengpc
     */
    public function setNext(Handler $handler);

    /**
     * 当前处理
     * @return mixed
     * @author chendashengpc
     */
    public function handler();
}

抽象类

abstract class BaseHandler implements Handler
{
    /**
     * 下一个请求类
     * @var Handler
     */
    protected Handler $next;
}

具体类

县教育局

/**
 * 县教育局
 */
class CountyEducationBureau extends BaseHandler
{
    /**
     * 下一个请求
     * @return mixed
     * @author chendashengpc
     */
    public function setNext(Handler $handler)
    {
        $this->next = $handler;
    }

    /**
     * 当前处理
     * @return mixed
     * @author chendashengpc
     */
    public function handler()
    {
        echo '我是县教育局,我这办不了,你去市教育局' . PHP_EOL;
        if ($this->next != null) {
            $this->next->handler();
        }

    }
}

市教育局

/**
 * 市教育局
 */
class MunicipalEducationBureau extends BaseHandler
{
    /**
     * 下一个请求
     * @return mixed
     * @author chendashengpc
     */
    public function setNext(Handler $handler)
    {
        $this->next = $handler;
    }

    /**
     * 当前处理
     * @return mixed
     * @author chendashengpc
     */
    public function handler()
    {
        echo '我是市教育局,我这办不了,你去省教育局' . PHP_EOL;
        if ($this->next != null) {
            $this->next->handler();
        }
    }
}

省教育局

/**
 * 省教育局
 */
class ProvincialEducationBureau extends BaseHandler
{

    /**
     * 下一个请求
     * @return mixed
     * @author chendashengpc
     */
    public function setNext(Handler $handler)
    {
        $this->next = $handler;
    }

    /**
     * 当前处理
     * @return mixed
     * @author chendashengpc
     */
    public function handler()
    {
        echo '我是省教育局,我这能办,提交资料就能办了' . PHP_EOL;
    }
}

客户端使用

$county = new CountyEducationBureau();
$municipal = new MunicipalEducationBureau();
$provincial = new ProvincialEducationBureau();


$county->setNext($municipal);
$municipal->setNext($provincial);

$county->handler();

输出

我是县教育局,我这办不了,你去市教育局
我是市教育局,我这办不了,你去省教育局
我是省教育局,我这能办,提交资料就能办了

UML

UML

优缺点

优点

  • 可以控制请求处理的顺序。
  • 单一职责原则。可对发起操作和执行操作的类进行解耦。
  • 开闭原则。可以在不更改现有代码的情况下在程序中新增处理者。

缺点

  • 部分请求可能未被处理。
分享到:
0

说点儿什么吧

头像

表情

本站由陈大剩博客程序搭建 | 湘ICP备2023000975号| Copyright © 2017 - 陈大剩博客 | 本站采用创作共用版权:CC BY-NC 4.0

站长统计| 文章总数[115]| 评论总数[9]| 登录用户[22]| 时间点[118]

logo

登入

社交账号登录