B5:责任链模式 Chain Of Responsibility

使多个对象都有机会处理处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着该链处理请求,直到有一个对象能够处理它为止.

相当于switch/case,在客户端指定了每一链的下一链.

UML

 

示例代码:

abstract class Handle
{
    protected $nextHandle;

    public function setNextHandle(Handle $handle)
    {
        $this->nextHandle = $handle;
    }

    abstract public function handleRequest($level);
}

class Handle1 extends Handle
{
    public function handleRequest($level)
    {
        if ($level > 0 && $level < 10) {
            echo 'Handle1 处理了';
        } elseif(!is_null($this->nextHandle)) {
            $this->nextHandle->handleRequest($level);
        }
    }
}

class Handle2 extends Handle
{
    public function handleRequest($level)
    {
        if ($level > 10 && $level < 100) {
            echo 'Handle2 处理了';
        } elseif(!is_null($this->nextHandle)) {
            $this->nextHandle->handleRequest($level);
        }
    }
}

class Handle3 extends Handle
{
    public function handleRequest($level)
    {
        if ($level > 100 && $level < 1000) {
            echo 'Handle3 处理了';
        } elseif(!is_null($this->nextHandle)) {
            $this->nextHandle->handleRequest($level);
        }
    }
}

$handle1 = new Handle1();
$handle2 = new Handle2();
$handle3 = new Handle3();
$handle1->setNextHandle($handle2);
$handle2->setNextHandle($handle3);

$handle1->handleRequest(600);

  

这个手动设置下一处理者,还是有点不方便.有时候设置出错,容易导致死循环,我们改进一下.

示例代码:

abstract class Handle
{
    abstract public function handleRequest($level);
}

class Handle1 extends Handle
{
    public function handleRequest($level)
    {
        if ($level > 0 && $level < 10) {
            echo 'Handle1 处理了';
            return true;
        }
    }
}

class Handle2 extends Handle
{
    public function handleRequest($level)
    {
        if ($level > 10 && $level < 100) {
            echo 'Handle2 处理了';
            return true;
        }
    }
}

class Handle3 extends Handle
{
    public function handleRequest($level)
    {
        if ($level > 100 && $level < 1000) {
            echo 'Handle3 处理了';
            return true;
        }
    }
}

class Context
{
    protected $chains = [];

    public function addHandle(Handle $handle)
    {
        $this->chains[] = $handle;
    }

    public function handleRequest($level)
    {
        foreach ($this->chains as $handler) {
            if ($handler->handleRequest($level)) {
                break;
            }
        }
    }
}

$context = new Context();
$context->addHandle(new Handle1());
$context->addHandle(new Handle2());
$context->addHandle(new Handle3());

$context->handleRequest(600);

  

我们将链的设置交给Context,Context维护了一个数组来保存设置的处理者.context中的handleRequest方法,循环从数组中读取并处理.在每个处理者类中,我们让其如果有处理,就返回true,在foreach循环中跳出循环,防止无用的循环继续下去.

 

当然有时候我们需要职责链的每个处理者挨个处理请求,也可以使用这种方法.

posted @ 2017-11-06 07:54  rorshach  阅读(251)  评论(0编辑  收藏  举报