PHP實現職責鏈設計模式

kolin發表於2023-01-17

參考文章地址:你也是業務開發?提前用這個設計模式預防產品加需求吧
實現原理看參考文章就好了 原文是用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 協議》,轉載必須註明作者和本文連結

相關文章