PHP设计模式 五
5 责任链模式
责任链模式,见名知意,流程是链式,通过链式的流程处理请求。
事务A/权限=1事务B/权限=2事务C/权限=3处理权限=3的事情,通过链式找到对应事务,将请求对象和接受对象解除耦合关系。沿着链式关系传递请求,直到请求被处理。事务A->事务B->事务C
应用范围
框架
Web 框架的中间件/过滤器/拦截器:如 Express/Koa 的中间件栈、Spring MVC 的 Filter 和 Interceptor、ASP.NET Core 的中间件管道。每个中间件可以决定处理请求、终止链、或传递给下一个。
HTTP 客户端拦截器:如vue3路由守卫,用于权限控制,或者是指对 HTTP 请求进行拦截处理(如 token 添加、错误处理),最后会返回next()。
安全框架:Spring Security 通过一系列 Filter组成安全过滤器链,依次处理认证、授权、CSRF 防护等。
事件处理系统:GUI 编程中的事件冒泡,如浏览器 DOM 事件从目标元素逐级冒泡到 document;Android 的 View 事件分发机制(dispatchTouchEvent → onInterceptTouchEvent → onTouchEvent)也是职责链的变体。
业务逻辑
多级审批流程:如 OA 系统中的请假审批(组长 → 经理 → 总监 → 总经理),报销审批、合同审批等。每级审批人是一个处理节点,可以批准、拒绝或转交。
工作流引擎:在复杂的工作流系统中,任务按预定顺序(链)在多个处理者间流转,每个节点执行特定业务操作或人工审批。
风控与审核:如内容审核系统(机器初审 → 敏感词过滤 → 人工复审 → 终审),每个节点对内容进行不同维度的检查。
数据处理
数据清洗与转换:ETL 流程中,一条数据依次经过“格式校验 → 缺失值填充 → 类型转换 → 脱敏处理”等一系列处理器。
参数校验与预处理:API 入口处,对输入参数进行链式校验:非空校验 → 格式校验(邮箱/手机号)→ 业务规则校验(如库存是否充足)。
规则引擎:一组业务规则形成链,按优先级依次匹配。例如电商促销规则:先检查是否满足满减门槛 → 再检查是否可用优惠券 → 最后检查是否享受会员折扣,任一规则匹配后可能终止或继续组合。
动态算法与策略选择
支付渠道路由:根据订单金额、用户偏好、渠道可用性等因素,依次尝试支付渠道:余额支付 → 银行卡 → 第三方支付(微信/支付宝),直到成功。
服务降级与熔断:在微服务调用中,形成降级链:优先尝试主服务 → 失败则尝试备用服务 → 再失败则返回本地缓存数据。
资源加载策略:如缓存加载:一级缓存(本地)→ 二级缓存(Redis)→ 数据库。任一层次命中则返回,否则继续向下。
游戏开发
伤害计算链:攻击命中后,依次经过“护甲减免 → 抗性减免 → 护盾吸收 → 最终伤害结算”等多个处理环节,每个环节可以修改伤害值。
技能效果链:一个技能触发后,可能附带多个效果:造成伤害 → 附加 debuff → 触发连击 → 回复自身生命值,这些效果可以组织成一条链顺序执行。
UI 事件穿透:处理点击事件时,从最上层 UI 元素向下或向上传递,直到有控件消费该事件。
代码实现
抽象类
abstractclassHandler{private $nextHandler;publicfunctionsetNext(Handler $nextHandler){$this->nextHandler = $nextHandler; }publicfunctionnext(){$this->nextHandler->handlerRequest(); }abstractpublicfunctionhandlerRequest(){} }
实现类
//校验authclassCheckAuthHandlerextendsHandler{ publicfunctionhandlerRequest(){ $request = request(); $token = $request->header("token");//校验token $checkAuth = $this->checkAuth();if(empty($checkAuth)){thrownew RequestException("token错误"); }return$this->next(); } }
//校验权限classCheckPermissionHandlerextendsHandler{publicfunctionhandlerRequest(){ $request = request(); $token = $request->header("token");//校验token $checkPermission = $this->checkPermission();if(empty($checkPermission)){thrownew RequestException("用户无权限"); }return$this->next(); } }
基础控制器
classControllerextendsHandler{publicfunctionhandlerRequest(){ $request = request();$this->doController($request); } }
控制器类
//文章类classArticleControllerextendsController(){publicfunctiondeleteArticle(){//删除文章 } }
实际调用
//设置链式调用顺序 $handlers = ["CheckAuthHandler::class","CheckPermissionHandler::class", ];//构建链式结构 $lastHandler = null;for($i=1;$i++;$i<count($handlers)){ $handler1 = $handlers[$i-1]; $handler2 = $handlers[$i]; $handler1->setNext($handler2); $lastHandler = $handler2; }//保证链式结构最后是controller $controller = new Controller(); $handler2->setNext($controller);