责任链模式实例:扣除用户金币/写入金币明细/发送消息
功能:
扣除用户金币,写入明细,并发送消息
以上三个动作任意一个动作失败,则请求终止
一.定义一个异常类:
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()}";