PHP Design Patterns (3) -- Chain of Responsibility (Chain of Responsibility) Pattern

My design pattern series articles
php design pattern (1) -- observer pattern -- spl standard writing
php design pattern (2) -- observer pattern -- using trait to improve writing
php design pattern (3) -- responsibility Chain (Chain of Responsibility) Pattern
PHP Design Pattern (4) -- Decorator Pattern



This time we discuss the chain of responsibility.

Analysis

In fact, the chain of responsibility imagines the middleware in software development. There is only one request, but there will be many processing objects, each processing object contains the next object, and each processing object has the right to process.

Primary role, the processing class, and its common interface
Secondary role, the request object.

There are a lot of codes on the Internet, mainly for an employee's request for leave, which is too boring. Next, I construct a requirement, assuming that the request is that the user wants to change his own password, so the request object contains the request url, user name, original password, and new password.
There is also a requirement that the user checks his followers without logging in for verification.
During processing, I will log all requests, here is a processing class.
During processing, some requests need to verify the user's password, and some do not. This is a login verification request.
During processing, if the request url is wrong, an error will be reported.

So in total, it is a log processor, a login verification processor, a password modification processor, and a query fan processor.
Experience, this mode can have a return value or no return value. random.
Lesson 2: Construct the chain of responsible handlers, in the client code, please be aware of this.

Code

<?php

/**
 * Common abstract interface of the processors of the chain of responsibility
 */
abstract class Handler
{
    protected $successor;
    
    // handle the request object
    abstract  public function handleRequest($request);
    
    // Set up the next handler.
    public function setSuccessor(Handler $next_handler){
        $this->successor = $next_handler;
    }
}

/**
 * This is the request object
 */
class Request
{
    public $url;
    public $username;
    public $password;
    public $request_parameter;
    public function __construct($url,$username, $password, array $request_parameter){
        $this->url=$url;
        $this->username=$username;
        $this->password=$password;
        $this->request_parameter=$request_parameter;
    }
}

/**
 * log handler
 */
class Log extends Handler
{
    public function  handleRequest($request)
    {
        echo "url:{$request->url}; request_parameter:" . json_encode($request->request_parameter)
            . PHP_EOL;
        if ($this->successor) { // Pass the request directly
            return $this->successor->handleRequest($request);
        }
        return ['code'=>0];
    }
}

/**
 * Identity verification processor, should use database, here is replaced by array
 */
class Verification extends Handler
{
    protected $all_user;
    protected $all_url;
    
    public function __construct(){
        $this->all_users = [
            'name1' =>'123',
            'name2' => '456',
        ];
        $this->check_urls = [
            'change_password',
        ];
    }
    
    private function continue_request($request){
        if ($this->successor) { // Pass the request directly
            return $this->successor->handleRequest($request);
        }
    }
    
    public function  handleRequest($request)
    {
        if (in_array( $request->url, $this->check_urls )) {
            if ( array_key_exists($request->username, $this->all_users ) &&
                 $request->password == $this->all_users[$request->username]  ) {
                return $this->continue_request($request);        
            } else {
                return ['code'=>0,'message'=>'user authentication error' ];
            }
        }else {
            return $this->continue_request($request);
        }
    }
}

/**
 * Modify the password processor
 * Modify the database code slightly.
 */
class ChangePassword extends Handler
{
    public function  handleRequest($request)
    {
        if ($request->url == 'change_password') {
            // Here you can continue to check whether the parameters are correct, the code is omitted
            return ['code'=>1,'data'=>
                  "Hello {$request->username}, the password is changed successfully, the new password is {$request->request_parameter['new_password']}"];
        }
        if ($this->successor) { // Pass the request directly
            return $this->successor->handleRequest($request);
        }
        return ['code'=>0,'message'=>'url is invalid'];
    }
}

/**
 * Check fans, replace the database code with an array
 */
class QueryFans extends Handler
{
    protected $all_user;
    
    public function __construct(){
        $this->all_users = [
            'name1' => 'Your fans are name3,name4',
            'name2' => 'Your fans are name5,name6,name7',
        ];
    }
    public function  handleRequest($request)
    {
        if ($request->url == 'query_fans') {
            if (array_key_exists( $request->username, $this->all_users )) {
                return ['code'=>1,'data'=> "{$request->username}您好,".
                   $this->all_users[ $request->username ] ];
            }else {
                return ['code'=>0,'message' =>'user does not exist' ];
            }
        }
        if ($this->successor) { // Pass the request directly
            return $this->successor->handleRequest($request);
        }
        return ['code'=>0,'message'=>'url is invalid'];
    }
    
}

/**
 * Client code, verifying the chain of responsibility design pattern
 */
class Client
{
    public function __construct(){
        
        $change_pass_handler = new ChangePassword();
        $query_handler = new QueryFans();
        $log_handler = new Log();
        $verification = new Verification();
        
        $log_handler->setSuccessor($verification);
        $verification->setSuccessor($change_pass_handler);
        $change_pass_handler->setSuccessor($query_handler);
        
        $request = new Request('luanxie_url', '', '', []);
        $result = $log_handler->handleRequest($request); // use log as first handler
        $this->print_result($result);
        
        // deliberately wrong password
        $request = new Request('change_password', 'name1', '1266', ['new_password'=>'124']);
        $result = $log_handler->handleRequest($request);
        $this->print_result($result);
        
        // Deliberately write non-existent users
        $request = new Request('change_password', 'name444', '123', ['new_password'=>'124']);
        $result = $log_handler->handleRequest($request);
        $this->print_result($result);
        
        // This time it's spec-compliant.
        $request = new Request('change_password', 'name1', '123', ['new_password'=>'124']);
        $result = $log_handler->handleRequest($request);
        $this->print_result($result);
        
        //Fan query, business logic stipulates: no need to verify the password, it doesn't matter if it is wrong
        $request = new Request('query_fans', 'name1', '12789', []);
        $result = $log_handler->handleRequest($request);
        $this->print_result($result);
        
    }
        
    private function print_result($result)
    {
        if ($result['code']==1) {
            echo $result['data'];
        }else {
            echo $result['message'];  
        }
        echo  PHP_EOL.PHP_EOL;
    }
}

new Client();


Results display

url:luanxie_url; request_parameter:[]
url is invalid

url:change_password; request_parameter:{"new_password":"124"}
User authentication error

url:change_password; request_parameter:{"new_password":"124"}
User authentication error

url:change_password; request_parameter:{"new_password":"124"}
Hello name1, the password has been changed successfully, the new password is 124

url:query_fans; request_parameter:[]
Hello name1, your fans are name3,name4

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326458841&siteId=291194637