PHP实现职责链设计模式

参考文章地址:你也是业务开发?提前用这个设计模式预防产品加需求吧
实现原理看参考文章就好了 原文是用go语言去实现,这里写一个php版本的实现方式,框架用的hyperf。
文件结构:
IndexController为调用端,UserInfoEntity用户实体用于存用户信息,flow里面的为各种处理流程
PHP实现职责链设计模式
IndexController

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Controller;

use App\Service\Entity\UserInfoEntity;
use App\Service\Flow\Cashier;
use App\Service\Flow\Clinic;
use App\Service\Flow\Pharmacy;
use App\Service\Flow\Reception;
use App\Service\StartHandler;

class IndexController extends AbstractController
{
    public function index()
    {
        $startHandler = new StartHandler();
        $userInfo = (new UserInfoEntity())->setName('zhangsan');
        $startHandler->setNextHandler(new Reception())
            ->setNextHandler(new Clinic())
            ->setNextHandler(new Cashier())
            ->setNextHandler(new Pharmacy());
        $startHandler->execute($userInfo);
    }
}

UserInfoEntity

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service\Entity;

class UserInfoEntity
{
    private string $name;

    private bool $registrationDone = false;

    private bool $doctorCheckUpDone = false;

    private bool $medicineDone = false;

    private bool $paymentDone = false;

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): UserInfoEntity
    {
        $this->name = $name;
        return $this;
    }

    public function isRegistrationDone(): bool
    {
        return $this->registrationDone;
    }

    public function setRegistrationDone(bool $registrationDone): UserInfoEntity
    {
        $this->registrationDone = $registrationDone;
        return $this;
    }

    public function isDoctorCheckUpDone(): bool
    {
        return $this->doctorCheckUpDone;
    }

    public function setDoctorCheckUpDone(bool $doctorCheckUpDone): UserInfoEntity
    {
        $this->doctorCheckUpDone = $doctorCheckUpDone;
        return $this;
    }

    public function isMedicineDone(): bool
    {
        return $this->medicineDone;
    }

    public function setMedicineDone(bool $medicineDone): UserInfoEntity
    {
        $this->medicineDone = $medicineDone;
        return $this;
    }

    public function isPaymentDone(): bool
    {
        return $this->paymentDone;
    }

    public function setPaymentDone(bool $paymentDone): UserInfoEntity
    {
        $this->paymentDone = $paymentDone;
        return $this;
    }
}

HandlerInterface

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service;

use App\Service\Entity\UserInfoEntity;

interface HandlerInterface
{
    public function setNextHandler(HandlerInterface $handler): HandlerInterface;

    public function execute(UserInfoEntity $info);

    public function do(UserInfoEntity $info);
}

AbstractHandler

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service;

use App\Service\Entity\UserInfoEntity;

class AbstractHandler implements HandlerInterface
{
    private HandlerInterface $nextHandler;

    public function setNextHandler(HandlerInterface $handler): HandlerInterface
    {
        $this->nextHandler = $handler;
        return $this->nextHandler;
    }

    public function execute(UserInfoEntity $info)
    {
        if (! empty($this->nextHandler)) {
            try {
                $this->nextHandler->do($info);
            } catch (\Exception $e) {
                return;
            }
            return $this->nextHandler->execute($info);
        }
    }

    public function do(UserInfoEntity $info)
    {
        // TODO: Implement do() method.
    }
}

StartHandler

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service;

class StartHandler extends AbstractHandler
{
}

Cashier

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service\Flow;

use App\Service\AbstractHandler;
use App\Service\Entity\UserInfoEntity;

class Cashier extends AbstractHandler
{
    public function do(UserInfoEntity $info)
    {
        echo '收费' . PHP_EOL;
        $info->setPaymentDone(true);
    }
}

Clinic

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service\Flow;

use App\Service\AbstractHandler;
use App\Service\Entity\UserInfoEntity;

class Clinic extends AbstractHandler
{
    public function do(UserInfoEntity $info)
    {
        echo '诊室' . PHP_EOL;
        $info->setDoctorCheckUpDone(true);
    }
}

Pharmacy

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service\Flow;

use App\Service\AbstractHandler;
use App\Service\Entity\UserInfoEntity;

class Pharmacy extends AbstractHandler
{
    public function do(UserInfoEntity $info)
    {
        echo '药房' . PHP_EOL;
        $info->setMedicineDone(true);
    }
}

Reception

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Service\Flow;

// 挂号
use App\Service\AbstractHandler;
use App\Service\Entity\UserInfoEntity;

class Reception extends AbstractHandler
{
    public function do(UserInfoEntity $info)
    {
        echo '挂号' . PHP_EOL;
        $info->setRegistrationDone(true);
    }
}

写一个单元测试跑一下indexController的index方法,结果如下:

PHP实现职责链设计模式

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 3

这个像 管道模式?

2周前 评论
kolin (楼主) 2周前
MArtian 1周前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!