The responsibility chain pattern of PHP design pattern

Posted by asa_carter on Sun, 28 Jun 2020 03:57:15 +0200

The model of responsibility chain belongs to the design model of object behavior.

Gof class diagram and explanation

GoF definition: allows multiple objects to process requests, thus avoiding the coupling between the sender and receiver of the request. Link these objects into a chain and pass the request along the chain until there is an object to process it.

GoF class diagram

code implementation

abstract class Handler
{
    protected $successor;
    public function setSuccessor($successor)
    {
        $this->successor = $successor;
    }
    abstract public function HandleRequst($request);
}

Define the abstract responsibility chain class, and use $success to save the subsequent chain.

class ConcreteHandler1 extends Handler
{
    public function HandleRequst($request)
    {
        if (is_numeric($request)) {
            return 'The request parameters are numbers:' . $request;
        } else {
            return $this->successor->HandleRequst($request);
        }
    }
}

class ConcreteHandler2 extends Handler
{
    public function HandleRequst($request)
    {
        if (is_string($request)) {
            return 'The request parameter is a string:' . $request;
        } else {
            return $this->successor->HandleRequst($request);
        }
    }
}

class ConcreteHandler3 extends Handler
{
    public function HandleRequst($request)
    {
        return 'I don't know what the request parameter is, guess?' . gettype($request);
    }
}

The main function of the three responsibility chains is to determine the type of data passed in. If it is a number, it is processed by the first class. If it is a string, it is processed by the second class. If it is of other types, the third class handles it uniformly.

$handle1 = new ConcreteHandler1();
$handle2 = new ConcreteHandler2();
$handle3 = new ConcreteHandler3();

$handle1->setSuccessor($handle2);
$handle2->setSuccessor($handle3);

$requests = [22, 'aaa', 55, 'cc', [1, 2, 3], null, new stdClass];

foreach ($requests as $request) {
    echo $handle1->HandleRequst($request) . PHP_EOL;
}

Call from the client, instantiate three responsibility chain instances in turn, and specify chain members. Create the request parameter, and then judge the result through the responsibility chain.

  • A very suitable scenario for the responsibility chain is to filter the request parameters layer by layer, just like we use office software such as nails when we work. When overtime or leave applications need to be submitted, the level of approval process is the most perfect explanation for this model
  • We can intercept the request and return it directly, or we can improve the content of the request and give it to the next class for processing, but at least one class needs to return the result.
  • Requests may not always be processed, or they may be returned or passed to the next processing class for processing without processing at all

We've been talking about the mobile phone manufacturing industry. Before that, we always gave it to the agent factory to carry out the assembly and production of mobile phones. This time, we set up a production line ourselves. And this assembly line is very similar to the responsibility chain mode, how to say, starting from the assembly of a mobile phone. Some operators put the main board of mobile phone (initial request) on the assembly line, and then workers start to add memory, CPU, camera (various responsibility chain classes for processing), during which, they will also be tested and adjusted to achieve the best factory performance. Finally, assemble a complete mobile phone and deliver it to the customer. Is this workflow very similar to the responsibility chain!!

Full code: https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain.php

example

It is still the SMS function, but this time we want to achieve a sub function of SMS content filtering. As you all know, we have strict regulations on advertising. Many words are marked as forbidden words in the advertising law, and even more serious words may cause unnecessary troubles. At this time, we need a set of filtering mechanism to Filter vocabulary. For different types of words, we can filter them through the responsibility chain. For example, the severely illegal words cannot pass this information. Some serious words that can be bypassed, we can replace or add stars, so that the client does not need a lot of if else… To make logical judgment, use the responsibility chain to let them approve step by step!!

Class diagram of SMS sending

Full source: https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain-filter-message.php

// Vocabulary filter chain
abstract class FilterChain
{
    protected $next;
    public function setNext($next)
    {
        $this->next = $next;
    }
    abstract public function filter($message);
}

// Forbidden words
class FilterStrict extends FilterChain
{
    public function filter($message)
    {
        foreach (['gun X', 'elastic X', 'poison X'] as $v) {
            if (strpos($message, $v) !== false) {
                throw new \Exception('This information contains sensitive words!');
            }
        }
        if ($this->next) {
            return $this->next->filter($message);
        } else {
            return $message;
        }
    }
}

// Warning vocabulary
class FilterWarning extends FilterChain
{
    public function filter($message)
    {
        $message = str_replace(['fight', 'Breast enhancement', 'tax evasion'], '*', $message);
        if ($this->next) {
            return $this->next->filter($message);
        } else {
            return $message;
        }
    }
}

// Mobile number plus star
class FilterMobile extends FilterChain
{
    public function filter($message)
    {
        $message = preg_replace("/(1[3|5|7|8]\d)\d{4}(\d{4})/i", "$1****$2", $message);
        if ($this->next) {
            return $this->next->filter($message);
        } else {
            return $message;
        }
    }
}

$f1 = new FilterStrict();
$f2 = new FilterWarning();
$f3 = new FilterMobile();

$f1->setNext($f2);
$f2->setNext($f3);

$m1 = "Now test chain 1: the sentence does not contain sensitive words, so you need to replace the word fight, and then add star: 13333333333 to the mobile phone number, so that the data can be displayed";
echo $f1->filter($m1);
echo PHP_EOL;

$m2 = "Now test chain 2: this statement can't go to the back because it contains poison X,Directly wrong!!! The sentence does not contain sensitive words. You need to replace the word fight, and then add the star: 13333333 to the mobile phone number, so that the data can be displayed";
echo $f1->filter($m2);
echo PHP_EOL;

explain

  • In this example, we do a variety of processing on the message content. When new requirements arise, we only need to add new filtering classes, and then adjust the execution order of the client.
  • Next is used to identify the next operation. Students who have used Laravel must immediately associate with middleware. Of course, the students who have used Node to develop the server are not unfamiliar. They have known this design pattern for a long time.
  • The application of responsibility chain is really extensive, which can be seen in various workflow software and middleware components. At the same time, with the pipeline idea under Linux, the advantages of this mode can be brought to the extreme
  • Laravel's middleware, interested friends turn over the source code, typical application of responsibility chain mode

Next issue

The responsibility chain seems to be a very high design pattern, which has mature application in many frameworks or systems at present. If you don't understand this pattern, you may be at a loss when reading or understanding some framework system knowledge. Next time, let's take a look at another familiar pattern, which is called the agent pattern.

===============

Official account: hard core project manager

Add wechat / QQ friends: [darkmaterzycoder / 149844827] free PHP and project management learning materials

Topics: Mobile PHP github Laravel