>  기사  >  백엔드 개발  >  한 기사로 PHP 디자인 패턴의 책임 사슬 모델 이해

한 기사로 PHP 디자인 패턴의 책임 사슬 모델 이해

齐天大圣
齐天大圣원래의
2020-08-08 08:20:111951검색

책임 체인 모델은 프로세서 체인을 따라 요청을 보내는 행동 설계 모델입니다. 요청을 받은 후 각 프로세서는 요청을 처리하거나 체인의 다음 프로세서로 요청을 전달할 수 있습니다. 체인의 각 프로세서에는 자체 처리 책임이 있으므로 이를 책임 체인 모델이라고 합니다.

Scenario

현재 시스템이 있고 이제 시스템에 대한 액세스를 제한하고 싶다고 가정해 보겠습니다. 첫 번째는 로그인 확인입니다. 이 시스템에 대한 모든 요청은 로그인이 필요합니다.

잠시 후 사장님은 크롤러 방지 프로그램을 추가해야겠다고 느꼈습니다. 사장님이 원래 인증코드에 바로 크롤러 방지 기능을 추가하는 게 가장 큰 임무입니다. 현재 로그인 확인 및 크롤러 방지 확인은 그리 복잡하지 않습니다. 그런데 며칠 후 사장님은 현재 한도 검증을 추가해야 한다고 느꼈는데... 며칠 뒤 사장님이..

검증과 관련된 코드 블록이 비대해져서 코드를 읽고 유지하기가 어려워졌습니다. 이때 책임 체인 모델을 사용하여 검증 기능 시스템을 다시 작성하면 다음과 같이 보일 것입니다.

한 기사로 PHP 디자인 패턴의 책임 사슬 모델 이해

책임 체인 모델을 통해 여러 프로세서가 요청을 처리할 수 있는 기회를 갖게 됩니다. 처리를 위해 원본 모듈을 여러 프로세서로 나누는 것은 단일 책임 원칙을 따르며 코드의 가독성을 크게 향상시킵니다. 또한, 새로운 검증 기능이 필요할 때 개폐 원리를 준수하는 새로운 프로세서를 추가하기만 하면 확장이 매우 쉽습니다.

책임 사슬 패턴 구조

책임 사슬 패턴 구조의 코드를 완성해 봅시다. 각 핸들러의 기능은 매우 간단합니다. 요청을 처리한 후 다음 요청 핸들러를 설정하는 것입니다. 다음은 샘플 코드입니다.

abstract class AHandler
{
    protected $nextHandler = null;
    
    public function setNext (AHandler $handler)
    {
        $this->nextHandler = $handler;
    }
    
    abstract public function handler ();
}
class Handler1 extends AHandler
{
    public function handler()
    {
        $handled = false;
        
        // 处理请求
        echo 'Handler1接受到了请求' . PHP_EOL;
        
        if (!$handled && $this->nextHandler) {
            $this->nextHandler->handler();
        }
    }
}
class Handler2 extends AHandler
{
    public function handler()
    {
        $handled = false;
        
        // 处理请求
        echo 'Handler2接受到了请求' . PHP_EOL;
        
        if (!$handled && $this->nextHandler) {
            $this->nextHandler->handler();
        }
    }
}
class Handler3 extends AHandler
{
    public function handler()
    {
        $handled = false;
        
        // 处理请求
        echo 'Handler3接受到了请求' . PHP_EOL;
        
        if (!$handled && $this->nextHandler) {
            $this->nextHandler->handler();
        }
    }
}

사용 코드 예는 다음과 같습니다.

$handler1 = new Handler1();
$handler2 = new Handler2();
$handler3 = new Handler3();
$handler1->setNext($handler2);
$handler2->setNext($handler3);

$handler1->handler();

위 코드로 책임 사슬의 구조가 완성되었음에도 불구하고 프로그래머가 비즈니스나 업무에 대해 명확하지 않은 경우 여전히 몇 가지 문제가 있습니다. 책임 사슬 모델을 사용하는 경우 핸들러 메서드에 다음 코드를 추가하는 것을 잊어버릴 수도 있습니다.

if (!$handled && $this->nextHandler) {
    $this->nextHandler->handler();
}

그러면 책임 사슬이 중단됩니다. 또한, 10개 이상의 프로세서가 있으면 10개의 새로운 프로세서가 생성되고 setNext가 9번 실행됩니다. 실수로 글을 잘못 쓰면 당황스럽습니다.

이제 위 코드를 수정해 보겠습니다.

abstract class AHandler
{
    protected $nextHandler = null;
    
    public function setNext (AHandler $handler)
    {
        $this->nextHandler = $handler;
    }
    
    // 使用了模板方法模式,防止程序员忘记写下段代码
    public function handler ()
    {
        if (!$this->doHandler() && $this->nextHandler) {
            $this->nextHandler->handler();
        }
    }
    
    abstract public function doHandler ();
}

class Handler1 extends AHandler
{
    public function doHandler()
    {
        $handled = false;
        
        // 处理请求
        echo 'Handler1接受到了请求' . PHP_EOL;
        
        return $handled;
    }
}
class Handler2 extends AHandler
{
    public function doHandler()
    {
        $handled = false;
        
        // 处理请求
        echo 'Handler2接受到了请求' . PHP_EOL;
        
        return $handled;
    }
}

class Handler3 extends AHandler
{
    public function doHandler()
    {
        $handled = false;
        
        // 处理请求
        echo 'Handler3接受到了请求' . PHP_EOL;
        
        return $handled;
    }
}

class HandlerChain
{
    private $handlerChains = [];
    
    public function __construct(array $handlerChains)
    {
        $this->handlerChains = $handlerChains;
    }
    
    public function addHandler (AHandler $handler)
    {
        $this->handlerChains[] = $handler;
    }
    
    public function handler ()
    {
        $hdCnt = count($this->handlerChains);
        
        for ($i = 0; $i < $hdCnt; $i ++) {
            if (isset($this->handlerChains[$i]) 
                  && isset($this->handlerChains[$i+1])) {
                $this->handlerChains[$i]->setNext($this->handlerChains[$i+1]);
            }
        }
        
        $this->handlerChains[0]->handler();
    }
}

그런 다음 다음과 같이 코드를 사용하세요.

$handler1 = new Handler1();
$handler2 = new Handler2();
$handler3 = new Handler3();

$handerChian = new HandlerChain([$handler1, $handler2, $handler3]);
$handerChian->handler();

더 간단한 구현 방법

실제로 더 간단한 구현 체인이 있습니다. 책임 모델 방법의 코드는 다음과 같습니다.

abstract class AHandler
{
    abstract public function handler ();
}

class Handler1 extends AHandler
{
    public function handler()
    {
        $handled = false;
        // 处理请求
        echo &#39;Handler1接受到了请求&#39; . PHP_EOL;
        return $handled;
    }
}

// Handler2、Handler3代码省略


class HandlerChain
{
    private $handlerChains = [];
    
    public function __construct(array $handlerChains)
    {
        $this->handlerChains = $handlerChains;
    }
    
    public function addHandler (AHandler $handler)
    {
        $this->handlerChains[] = $handler;
    }
    
    public function handler ()
    {
        foreach ($this->handlerChains as $handler) {
            if ($handler->handler()) {
                break;
            }
        }
    }
}

Summary

책임 모델 체인을 통해 여러 프로세서가 요청을 처리할 수 있습니다. 처리를 위해 원본 모듈을 여러 프로세서로 나누는 것은 단일 책임 원칙을 따르며 코드의 가독성을 크게 향상시킵니다. 또한, 새로운 기능이 필요할 때 새로운 프로세서를 추가하기만 하면 확장이 매우 쉽습니다.

일반 디자인 패턴의 정의는 핸들러가 요청을 처리할 수 없으면 요청을 다음 핸들러로 전달한다는 것입니다. 실제로 각 프로세서가 요청을 처리하는 변형도 있습니다.

위 내용은 한 기사로 PHP 디자인 패턴의 책임 사슬 모델 이해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.