Home  >  Article  >  Backend Development  >  Php design patterns: behavioral patterns (1)

Php design patterns: behavioral patterns (1)

巴扎黑
巴扎黑Original
2016-11-12 11:47:161020browse

In the previous article, we talked about structural patterns. Structural patterns discuss the structure of classes and objects. There are 7 types in total. Today we will introduce behavioral patterns.

1. What is a behavioral pattern?

Behavioral pattern:

                                                                                                                                                                                                                                                                                ourselves a In short, it is the question of what role classes and objects play, and how to play this role.

2. Types of behavioral patterns

Generally divided into three categories: common patterns, known patterns, deep patterns

Common patterns include: template method pattern, command pattern, iterator pattern, observer Model, intermediary mode, status mode, responsibilities chain mode, strategy mode

Knowledge mode includes: Memorandum Mode

Deep mode includes: interpreter mode, visitor mode

common mode

1, template method mode mode (Template):

Define the algorithm skeleton in an operation, and defer some implementation steps to subclasses. Just like a soy milk machine, no matter whether red beans or black beans are put in, what comes out is soy milk.

Advantages: Good scalability, encapsulates unchanged code, and expands variable code.

Disadvantages: Poor flexibility, unable to change the skeleton part.

Application scenario: In a category or group of things with common characteristics.

Code implementation

Php code

<?php  
  
/** 
 * 优才网公开课示例代码 
 * 
 * 模板方法模式 Template 
 * 
 * @author 优才网全栈工程师教研组 
 * @see http://www.ucai.cn 
 */  
  
function output($string) {  
    echo    $string . "\n";  
}  
  
class Request {  
  
    public $token = &#39;&#39;;  
  
    public function __construct() {  
        $this->token    = &#39;0c6b7289f5334ed2b697dd461eaf9812&#39;;  
    }  
  
}  
  
class Response {  
  
    public function render($content) {  
        output(sprintf(&#39;response-render: %s&#39;, $content));  
    }  
  
    public function redirect($uri) {  
        output(sprintf(&#39;response-redirect: %s&#39;, $uri));  
    }  
  
    public function json($data) {  
        output(sprintf(&#39;response-data: %s&#39;, json_encode($data)));  
    }  
  
}  
  
 //父类,抽象类  
abstract class Controller{  
    //封装了输入输出  
    protected $request;  
    protected $response;  
  
    //返回数据  
    protected $data = &#39;data&#39;;  
  
    public function __construct($request, $response){  
        $this->request = $request;  
        $this->response = $response;  
    }  
  
    //执行请求函数,定义总体算法(template method),final防止被复写(不允许子类改变总体算法)  
    public final function execute(){  
        $this->before();  
        if ($this->valid()){  
            $this->handleRequest();  
        }  
        $this->after();  
    }  
  
    //定义hook method before,做一些具体请求的前置处理  
    //非abstract方法,子类可以选择覆盖或不覆盖,默认什么都不做  
    protected function before(){  
  
    }  
  
    //定义hook method valid,做请求的数据验证  
    //非abstract方法,子类可以选择覆盖或不覆盖,默认返回验证通过  
    protected function valid(){  
        return true;  
    }  
  
    //定义hook method handleRequest,处理请求  
    //定义为abstract方法,子类必须实现或也声明为抽象方法(由子类的子类负责实现)  
    abstract function handleRequest();  
  
    //定义hook method after,做一些请求的后置处理  
    //非abstract方法,子类可以选择覆盖或不覆盖,默认直接输出数据  
    protected function after(){  
        $this->response->render($this->data);  
    }  
}  
  
//子类1,实现父类开放的具体算法  
class User extends Controller{  
    //覆盖before方法,实现具体算法,这是一个处理用户数据操作的控制器  
    //因此,我们选择在before里面判断用户是否已经登录了,这里简单判断下session数据  
    function before(){  
        if (emptyempty($_SESSION[&#39;auth&#39;])){  
            //没登录就直接跳转了,不再执行后续的操作  
            $this->response->redirect("user/login.php");  
        }  
    }  
  
    //覆盖valid方法,这里我们验证用户提交数据中有没有带验证token  
    function valid(){  
        if (isset($this->request->token)){  
            return true;  
        }  
        return false;  
    }  
  
    //覆盖handleRequest方法,必选,以为父类中声明了abstract了  
    function handleRequest(){  
        //做具体处理,一般根据参数执行不同的业务逻辑  
    }  
  
    //这个类我们选择不覆盖after方法,使用默认处理方式  
}  
  
//子类2,实现父类开放的具体算法  
class Post extends Controller{  
    //这个类我们选择不覆盖before方法,使用默认处理方式  
  
    //这个类我们选择不覆盖valid方法,使用默认处理方式  
  
    //覆盖handleRequest方法,必选,以为父类中声明了abstract了  
    function handleRequest(){  
        //做具体处理,一般根据参数执行不同的业务逻辑  
        $this->data = array(&#39;title&#39; => &#39;ucai&#39;);  
    }  
  
    //覆盖after方法,使用json格式输出数据  
    function after(){  
        $this->response->json($this->data);  
    }  
}  
  
  
  
class Client {    
        
    public static function test(){    
  
        $request        = new Request();  
        $response       = new Response();  
  
        //最终调用  
        $user = new User($request, $response);  
        $user->execute();  
  
  
        //最终调用  
        $post = new Post($request, $response);  
        $post->execute();  
  
    }    
        
}    
    
Client::test();

2. Command mode (Command):


The behavior requester is decoupled from the behavior implementer. Just like the "salute" in the military, whoever hears this order will make a standard salute.

Benefits: Easy to add and modify behaviors, easy to aggregate multiple commands.

Disadvantages: Causes too many specific command classes.

Application scenario: Perform the same operation on the object to be operated.

Code implementation

Php code

<?php  
/** 
 * 优才网公开课示例代码 
 * 
 * 命令模式 Command 
 * 
 * @author 优才网全栈工程师教研组 
 * @see http://www.ucai.cn 
 */  
  
function output($string) {  
    echo    $string . "\n";  
}  
  
class Document {  
  
    private $name = &#39;&#39;;  
  
    public function __construct($name) {  
        $this->name = $name;  
    }  
  
    public function showText() {  
        output(sprintf("showText: %s", $this->name));  
    }  
  
    public function undo() {  
        output(sprintf("undo-showText: %s", $this->name));  
    }  
  
}  
  
class Graphics {  
  
    private $name = &#39;&#39;;  
  
    public function __construct($name) {  
        $this->name = $name;  
    }  
  
    public function drawCircle() {  
        output(sprintf("drawCircle: %s", $this->name));  
    }  
  
    public function undo() {  
        output(sprintf("undo-drawCircle: %s", $this->name));  
    }  
  
}  
  
class Client {  
      
    public static function test() {  
  
        $document       = new Document(&#39;A&#39;);  
        $graphics       = new Graphics(&#39;B&#39;);  
  
        $document->showText();  
        $graphics->drawCircle();  
  
        $document->undo();  
  
    }  
  
}  
  
Client::test();  
  
  
<?php  
  
/** 
 * 优才网公开课示例代码 
 * 
 * 命令模式 Command 
 * 
 * @author 优才网全栈工程师教研组 
 * @see http://www.ucai.cn 
 */  
  
function output($string) {  
    echo    $string . "\n";  
}  
  
interface Command {  
    public function execute();  
    public function undo();  
}  
  
class Document implements Command {  
  
    private $name = &#39;&#39;;  
  
    public function __construct($name) {  
        $this->name = $name;  
    }  
  
    public function execute() {  
        output(sprintf("showText: %s", $this->name));  
    }  
  
    public function undo() {  
        output(sprintf("undo-showText: %s", $this->name));  
    }  
  
}  
  
class Graphics implements Command {  
  
    private $name = &#39;&#39;;  
  
    public function __construct($name) {  
        $this->name = $name;  
    }  
  
    public function execute() {  
        output(sprintf("drawCircle: %s", $this->name));  
    }  
  
    public function undo() {  
        output(sprintf("undo-drawCircle: %s", $this->name));  
    }  
  
}  
  
class Client {  
      
    public static function test() {  
  
        $array          = array();  
  
        array_push($array, new Document(&#39;A&#39;));  
        array_push($array, new Document(&#39;B&#39;));  
        array_push($array, new Graphics(&#39;C&#39;));  
        array_push($array, new Graphics(&#39;D&#39;));  
          
        foreach ($array as $command) {  
            $command->execute();  
        }  
  
        $top            = array_pop($array);  
        $top->undo();  
  
    }  
  
}  
  
Client::test();

<?php  
  
/** 
 * 优才网公开课示例代码 
 * 
 * 命令模式 Command 
 * 
 * @author 优才网全栈工程师教研组 
 * @see http://www.ucai.cn 
 */  
  
function output($string) {  
    echo    $string . "\n";  
}  
  
interface Command {  
    public function execute();  
    public function undo();  
}  
  
class Document {  
  
    private $name = &#39;&#39;;  
  
    public function __construct($name) {  
        $this->name = $name;  
    }  
  
    public function showText() {  
        output(sprintf("showText: %s", $this->name));  
    }  
  
    public function undo() {  
        output(sprintf("undo-showText: %s", $this->name));  
    }  
  
}  
  
class Graphics {  
  
    private $name = &#39;&#39;;  
  
    public function __construct($name) {  
        $this->name = $name;  
    }  
  
    public function drawCircle() {  
        output(sprintf("drawCircle: %s", $this->name));  
    }  
  
    public function undo() {  
        output(sprintf("undo-drawCircle: %s", $this->name));  
    }  
  
}  
  
class DocumentCommand implements Command {  
  
    private $obj = &#39;&#39;;  
  
    public function __construct(Document $document) {  
        $this->obj = $document;  
    }  
  
    public function execute() {  
        $this->obj->showText();  
    }  
  
    public function undo() {  
        $this->obj->undo();  
    }  
  
}  
  
class GraphicsCommand implements Command {  
  
    private $obj = &#39;&#39;;  
  
    public function __construct(Graphics $graphics) {  
        $this->obj = $graphics;  
    }  
  
    public function execute() {  
        $this->obj->drawCircle();  
    }  
  
    public function undo() {  
        $this->obj->undo();  
    }  
  
}  
  
  
class Client {  
      
    public static function test() {  
  
        $array          = array();  
  
        array_push($array, new DocumentCommand(new Document(&#39;A&#39;)));  
        array_push($array, new DocumentCommand(new Document(&#39;B&#39;)));  
        array_push($array, new GraphicsCommand(new Graphics(&#39;C&#39;)));  
        array_push($array, new GraphicsCommand(new Graphics(&#39;D&#39;)));  
          
        foreach ($array as $command) {  
            $command->execute();  
        }  
  
        $top            = array_pop($array);  
        $top->undo();  
  
    }  
  
}  
  
Client::test();

3. Iterator pattern (Iterator):

Access the contents of the aggregate object without exposing the internal structure. Just like a double-color ball lottery draw, seven balls are shaken out every time, and the winning number combination that is not seven balls cannot be shaken.

Benefits: Traverse a collection in different ways.

Disadvantages: Each time it is traversed, the entire collection is traversed, and elements cannot be taken out individually.

Application scenario: All elements in the collection need to be operated.

Code implementation

Php code

<?php  
  
/** 
 * 优才网公开课示例代码 
 * 
 * 迭代器模式 Iterator 
 * 
 * @author 优才网全栈工程师教研组 
 * @see http://www.ucai.cn 
 */  
  
function output($string) {  
    echo    $string . "\n";  
}  
  
class RecordIterator implements Iterator{  
  
    private $position = 0;  
  
    //注意:被迭代对象属性是私有的  
    private $records = array();    
  
    public function __construct(Array $records) {  
        $this->position = 0;  
        $this->records = $records;  
    }  
  
    function rewind() {  
        $this->position = 0;  
    }  
  
    function current() {  
        return $this->records[$this->position];  
    }  
  
    function key() {  
        return $this->position;  
    }  
  
    function next() {  
        ++$this->position;  
    }  
  
    function valid() {  
        return isset($this->records[$this->position]);  
    }  
}  
  
class PostListPager {  
  
    protected $record   = array();  
    protected $total    = 0;  
    protected $page     = 0;  
    protected $size     = 0;  
  
    public function __construct($category, $page, $size) {  
  
        $this->page     = $page;  
        $this->size     = $size;  
  
        // query db  
  
        $total          = 28;  
        $this->total    = $total;  
  
        $record     = array(  
                        0 => array(&#39;id&#39; => &#39;1&#39;),  
                        1 => array(&#39;id&#39; => &#39;2&#39;),  
                        2 => array(&#39;id&#39; => &#39;3&#39;),  
                        3 => array(&#39;id&#39; => &#39;4&#39;),  
                    );  
  
        //  
        $this->record   = $record;  
  
    }  
  
    public function getIterator() {  
        return  new RecordIterator($this->record);  
    }  
  
    public function getMaxPage() {  
        $max    = intval($this->total / $this->size);  
        return  $max;  
    }  
  
    public function getPrevPage() {  
        return  max($this->page - 1, 1);  
    }  
  
    public function getNextPage() {  
        return  min($this->page + 1, $this->getMaxPage());  
    }  
  
}  
  
class Client {    
        
    public static function test(){    
  
        $pager      = new PostListPager(1, 2, 4);  
  
        foreach ($pager->getIterator() as $key => $val) {  
            output(sprintf(&#39;Key[%d],Val[%s]&#39;, $key, json_encode($val)));  
        }  
  
        output(sprintf(&#39;MaxPage[%d]&#39;, $pager->getMaxPage()));  
        output(sprintf(&#39;Prev[%d]&#39;, $pager->getPrevPage()));  
        output(sprintf(&#39;Next[%d]&#39;, $pager->getNextPage()));  
  
        $iterator       = $pager->getIterator();  
        while($iterator->valid()){  
            print_r($iterator->current());  
            $iterator->next();  
        }  
        $iterator->rewind();  
  
    }    
        
}    
    
Client::test();

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn