在体制内,我们办理什么业务或者提出什么方案,大多数情况下都需要走一定的审批流程,大到以一家公司的方案审批流程,小到在想向学校提出请假请求,这中间我们的请求都有可能被流程中那个的某一环节得到处理。由于笔者对向学校请假的千辛万苦记忆深刻,现在就以向学校请假为例子来演示一下职责链的使用。
假设现在请假一天内只需要向任课老师请假,请假1~3天的向学院辅导员请假,请假大于三天的要向学院领导请假。在这个模型中,我们的请求会依次向上级领导传递,直到请求达到的单位具有处理该请求的权利。
首先先来定义我们的请假类(也就是请求):
class request{
//请假天数
public $days;
public function __construct($num){
$this->days=$num;
}
public function setDays($num){
$this->days=$num;
}
}
接下来定义各级单位(也就是处于职责链上处理请求的对象).
定义抽象处理者:
abstract class handler{
protected $successor;
public function __construct($successor){
$this->successor=$successor;
}
public function setSuccessor(handler $successor){
$this->successor=$successor;
}
abstact function handle(request $request);
}
定义具体处理者:
class teacher extends handler{
public $name='任课老师';
function handle(request $request){
if($request->days <1){
echo "$this->name:批准{$request->days}天假期<br>";
}else{
$this->successor->handle($request);
}
}
}
class counsellor extends handler{
public $name='辅导员';
function handle(request $request){
if($request->days<=3){
echo "$this->name:批准{$request->days}天假期<br>";
}else{
$this->successor->handle($request);
}
}
}
class leader extends handler{
public $name='学院领导';
function handle(request $request){
if($request->days <7){
echo "$this->name:批准{$request->days}天假期<br>";
}else{
echo "请假这么多天,你自己看着办<br>";
//$this->successor->handle($request);
}
}
}
接下来我们就可以通过在客户端中设置处理者的下一级处理者,从而构成职责链,是的,我们可以灵活的调整职责链上各个对象的位置顺序和调整整个职责链的长度。
//先构造好职责链
$leader=new leader(null);
$counsellor=new counsellor($leader);
$teacher=new teacher($counsellor);
//实例化一个请求后传递请求给位于第一个节点的处理者
$request=new request(0.5);
$teacher->handle($request);
echo "<hr>";
$request->setDays(2);
$teacher->handle($request);
echo "<hr>";
$request->setDays(5);
$teacher->handle($request);
echo "<hr>";
$request->setDays(10);
$teacher->handle($request);
echo "<hr>";
运行结果:
总结
当需要根据请求的某个属性值将请求分发给权限不同的处理对象时候,可以采用职责链模式,将这些处理对象按照一定的顺序串联起来,使得每个对象都有机会处理请求,如果处理不了则将请求传递到下一个处理对象,直到有对象来处理这个请求,要避免请求分发到职责链的最后仍得不到处理的情况。