责任链模式( `Chain of Responsibility Pattern`): 为请求创建了一个接收者对象的链,并沿这条链传递该请求,直到有对象处理它为止。这种模式能够给予请求的类型,对请求的发送者和接收者进行解耦。
结构图
为什么需要责任链模式
1、将请求的发送者和请求的处理者解耦了。责任链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递。
2、 发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任
例子1-模拟审批流程
抽象类Manager编写具体执行方法。编写处理核心
namespace App\ChainOfResponsibilities;
abstract class manager
{
public $data; //用于加载数据内容
public $myStep=0;//当前状态,这个很重要
public $leader=false;//很重要,设置自己的领导是谁
public $myName="";//当前审批者的名字
public function setLeader($leader)
{
$this->leader=$leader;//设置领导, 关键方法,也就是形成 责任链的关键
}
function __construct()
{
//读取我们的数据、比方是数据库读取
$this->data=json_decode(file_get_contents(__DIR__."/data.json"));
}
public function step($msg){
//很重要,代表审批
//只有当data的step和自己的myStep 相等时才会处理
if($this->data->step==$this->myStep) //代表当前状态 是自己要处理的 状态
{
//判断 自己的领导是否有,如果有 那么 我们把控制权交给领导
if($this->leader)
{
$this->data->step=$this->leader->myStep;//交控制权
file_put_contents(__DIR__."/data.json",json_encode($this->data));//保存状态
}
else
{
echo "审批已经结束.";
}
//在这执行审批通过的 具体
echo $msg."审批者是:".$this->myName;
}
else
{
if($this->leader) //让自己的领导去审批 .leader就是维护整个类的 链
$this->leader->step($msg);
}
}
}
设置角色类
DirectorLeader.php经理
namespace App\ChainOfResponsibilities;
class DirectorLeader extends manager
{
public $myName="经理";
public $myStep=1;
}
Headman.php
namespace App\ChainOfResponsibilities;
class Headman extends manager
{
public $myName="主管";
public $myStep=0;
}
LastLeader.php
namespace App\ChainOfResponsibilities;
class LastLeader extends manager
{
public $myName="董事长";
public $myStep=2;
}
设置一个保存数据的类
namespace App\ChainOfResponsibilities;
class save
{
/**
* 默认创建数据是第一个编写者
* 初始值为0。第一步。
* @param $data
* @return boolean;
*/
public function createData($data)
{
$bool=(bool)file_put_contents(__DIR__.'/data.json',json_encode(['step'=>0,"content"=>"测试内容"]));
return $bool;
}
}
前段调用代码
//这里面最关键的是 1)确定第一个领导是谁 2)并要维护各个领导之间的关系
$busLeader=new Headman(); //第一个领导
$DirectorLeader=new DirectorLeader();
$lastLeader=new LastLeader();
//下面还是维护关系责任链组装
$busLeader->setLeader($DirectorLeader);
$DirectorLeader->setLeader($lastLeader);
$busLeader->step("审批通过");
核心代码在于manager
类中public function step($msg)
方法。最后一个对象没有设置leader对象就结束。一级到下一级。mystep可以设置任意的字符串类型或者整数类型