责任链模式实例:扣除用户金币/写入金币明细/发送消息

功能:

扣除用户金币,写入明细,并发送消息

以上三个动作任意一个动作失败,则请求终止

 

一.定义一个异常类:

class HandleException extends Exception
{
}

  

二.定义一个虚拟类:

abstract class Handle
{
    protected $nextHandle;

    public function setNextHandle(Handle $handle)
    {
        $this->nextHandle = $handle;
    }

    abstract public function handleRequest($request);
}

  

三.用户金币类:

class UserMoney extends Handle
{
    private $uid;
    private $money;

    public function __construct($uid, $money)
    {
        $this->uid      = $uid;
        $this->money    = $money;
    }

    public function handleRequest($request)
    {
        if ($this->money >= $request->money) {
            echo '扣除金币成功<br>';
            $this->money -= $request->money;

            // 给请求附加新的金币,便于金币明细记录
            $request->newMoney = $this->money;

            if ($this->nextHandle) {
                $this->nextHandle->handleRequest($request);
            }
        } else {
            throw new HandleException('金币不足', 2001);
        }
    }
}

  

四.金币明细类:

/**
 * 金币明细
 * Class UserMoneyDetail
 */
class UserMoneyDetail extends Handle
{
    public function writeDb($request)
    {
        echo "写入金币明细成功,新的金币数目为{$request->newMoney}<br>";
        return true;
    }

    public function handleRequest($request)
    {
        if ($this->writeDb($request)) {
            if ($this->nextHandle) {
                $this->nextHandle->handleRequest($request);
            }
        } else {
            throw new HandleException('金币不足', 2002);
        }
    }
}

  

五.发送消息类:

class Message extends Handle
{
    public function sendMessage($request)
    {
        echo "UID为{$request->uid}的用户减少了{$request->money}金币,减少的后金币为{$request->newMoney}";
        return true;
    }

    public function handleRequest($request)
    {
        if (! $this->sendMessage($request)) {
            throw new HandleException('发送邮件出错', 2003);
        }
    }
}

  

六.调用

$request = (object) ['uid' => 10, 'money' => 500];

try {
    $userMoney          = new UserMoney($request->uid, 300);
    $userMoneyDetail    = new UserMoneyDetail();
    $message            = new Message();

    $userMoney->setNextHandle($userMoneyDetail);
    $userMoneyDetail->setNextHandle($message);

    $userMoney->handleRequest($request);
} catch (HandleException $e) {
    echo "发生错误:{$e->getMessage()}";
}

  

我们手动设置了每个责任类的下一链,我们还可以建立一个上下文类,来统一管理一系列的动作;关键性更改如下:

取消设置下一链

abstract class Handle
{
    abstract public function handleRequest($request);
}

  

class UserMoney extends Handle
{
    private $uid;
    private $money;

    public function __construct($uid, $money)
    {
        $this->uid      = $uid;
        $this->money    = $money;
    }

    public function handleRequest($request)
    {
        if ($this->money >= $request->money) {
            echo '扣除金币成功<br>';
            $this->money -= $request->money;

            // 给请求附加新的金币,便于金币明细记录
            $request->newMoney = $this->money;
        } else {
            throw new HandleException('金币不足', 2001);
        }
    }
}

  

创建一个context类

 

class Context
{
    protected $chains = [];

    public function addChain(Handle $handle)
    {
        $this->chains[] = $handle;
    }

    public function handle($request) {
        foreach ($this->chains as $handle) {
            $handle->handleRequest($request);
        }
    }
}

  

调用:

$request = (object) ['uid' => 10, 'money' => 300];


try {
    $context = new Context();

    $userMoney          = new UserMoney($request->uid, 1000);
    $userMoneyDetail    = new UserMoneyDetail();
    $message            = new Message();

    $context->addChain($userMoney);
    $context->addChain($userMoneyDetail);
    $context->addChain($message);

    $context->handle($request);
} catch (HandleException $e) {
    echo "发生错误:{$e->getMessage()}";

  

posted @ 2018-04-06 21:44  rorshach  阅读(556)  评论(0编辑  收藏  举报