Maison >développement back-end >tutoriel php >Comprendre le modèle de chaîne de responsabilité du modèle de conception PHP dans un article

Comprendre le modèle de chaîne de responsabilité du modèle de conception PHP dans un article

齐天大圣
齐天大圣original
2020-08-08 08:20:112000parcourir

Le modèle de chaîne de responsabilité est un modèle de conception comportementale. La demande est envoyée le long de la chaîne du processeur. Après avoir reçu la demande, chaque processeur peut traiter la demande ou transmettre la demande au processeur suivant de la chaîne. Chaque processeur de la chaîne a ses propres responsabilités de traitement, c'est ce qu'on appelle le modèle de chaîne de responsabilité.

Scénario

Supposons qu'il existe actuellement un système et que nous souhaitons maintenant restreindre l'accès au système. La première est la vérification de la connexion. Toutes les demandes adressées à ce système doivent être connectées pour être obtenues.

Au bout d'un moment, le patron a estimé qu'un programme anti-crawler devait être ajouté. Le patron a la tâche la plus importante. Vous ajoutez immédiatement la fonction anti-crawler au code de vérification d'origine. À l’heure actuelle, la vérification de connexion et la vérification anti-crawler ne sont pas très compliquées. Mais au bout de quelques jours, le patron a estimé qu'il fallait ajouter la vérification des limites actuelles... Quelques jours plus tard, le patron...

Le bloc de code concernant la vérification est devenu volumineux, ce qui rend le code difficile à lire et à maintenir. À l'heure actuelle, si nous utilisons le modèle de chaîne de responsabilité pour réécrire le système de fonction de vérification, cela ressemblera à ce qui suit :

Comprendre le modèle de chaîne de responsabilité du modèle de conception PHP dans un article

À travers le modèle de chaîne de responsabilité, plusieurs processeurs Il est possible de traiter la demande. La division du module d'origine en plusieurs processeurs pour le traitement est conforme au principe de responsabilité unique et améliore considérablement la lisibilité du code. De plus, il est très facile de l'étendre lorsque de nouvelles fonctions de vérification sont nécessaires, il suffit d'ajouter un nouveau processeur, qui respecte le principe d'ouverture et de fermeture.

Structure de modèle de chaîne de responsabilité

Complétons le code d'une structure de modèle de chaîne de responsabilité ci-dessous. La fonction de chaque gestionnaire est très simple, il s'agit de gérer la requête puis de configurer le gestionnaire de requête suivant. Voici un exemple de code :

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();
        }
    }
}

L'exemple de code d'utilisation est le suivant :

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

$handler1->handler();

Bien que le code ci-dessus complète la structure de la chaîne de responsabilité, il reste encore quelques problèmes. Le programmeur ne comprend pas le modèle commercial ou de chaîne de responsabilité. Si vous êtes trop clair, vous risquez d'oublier d'ajouter le code suivant à la méthode du gestionnaire :

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

Cela entraînera l'interruption de la chaîne de responsabilité. De plus, si nous avons 10 processeurs ou plus, alors 10 nouveaux processeurs seront créés, puis setNext sera exécuté 9 fois. Si vous écrivez accidentellement quelque chose de mal, vous serez gêné.

Maintenant, modifions le code ci-dessus. Le code modifié est le suivant :

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();
    }
}

Ensuite, utilisez le code comme suit :

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

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

Plus facile. Méthode de mise en œuvre

En fait, il existe un moyen plus simple de mettre en œuvre le modèle de chaîne de responsabilité, le code est le suivant :

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;
            }
        }
    }
}

Résumé

Grâce au modèle de chaîne de responsabilité, plusieurs processeurs ont la possibilité de traiter les demandes. La division du module d'origine en plusieurs processeurs pour le traitement est conforme au principe de responsabilité unique et améliore considérablement la lisibilité du code. De plus, il est très facile de l'étendre lorsque de nouvelles fonctions sont nécessaires, il suffit d'ajouter de nouveaux processeurs.

La définition du modèle de conception général est que si le gestionnaire ne peut pas gérer la demande, il transmettra la demande au gestionnaire suivant. En fait, il existe également une variante, c'est-à-dire que chaque processeur traitera la requête.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn