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


    功能:

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

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

    一.定义一个异常类:

    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()}";
    

      

  • 相关阅读:
    JDBC 详解
    Class.forName() 详解
    23种设计模式
    MVC 模式
    Ant 打包 问题
    Jedis操作Redis--SortedSet类型 (会自然排序)
    在JSP中常见问题,防止SpringMVC拦截器拦截js等静态资源文件的解决方案
    在idea中使用@Test注解报错的解决方案
    判断返回的对象是否为空
    使用标准的日期格式化过程
  • 原文地址:https://www.cnblogs.com/itfenqing/p/8729024.html
Copyright © 2020-2023  润新知