>백엔드 개발 >PHP 튜토리얼 >Php 디자인 패턴: 행동 패턴 (1)

Php 디자인 패턴: 행동 패턴 (1)

巴扎黑
巴扎黑원래의
2016-11-12 11:47:161079검색

이전 기사에서는 구조적 패턴에 대해 이야기했습니다. 구조적 패턴은 클래스와 객체의 구조를 논의합니다. 총 7가지 종류가 있습니다. 오늘은 행동 패턴을 소개하겠습니다.

1. 행동 패턴이란 무엇인가요?

행동 패턴:

클래스와 객체 간의 의사소통과 책임을 설명합니다. 간단히 말해서, 클래스와 객체가 어떤 역할을 하는지, 그리고 이 역할을 어떻게 수행할 것인지에 대한 질문이다.

2. 행동 패턴의 유형

일반적으로 세 가지 범주로 나뉩니다: 공통 패턴, 알려진 패턴, 심층 패턴

공통 패턴에는 템플릿 방법이 포함됩니다. 패턴, 명령 패턴, 반복자 패턴, 관찰자 ​​패턴, 중재자 패턴, 상태 패턴, 책임 사슬 패턴, 전략 패턴

알려진 패턴: 메모 패턴

깊이 모드: 통역사 모드, 방문자 모드

공통 모드

1. 템플릿 메서드 모드(템플릿):

작업 알고리즘 뼈대를 정의하고 일부 구현 단계를 하위 클래스로 연기합니다. 두유 기계처럼 팥을 넣어도 검은콩을 넣어도 두유가 나옵니다.

장점: 확장성이 좋고 변경되지 않은 코드를 캡슐화하며 변수 코드를 확장합니다.

단점: 유연성이 약하고 뼈대 부분을 변경할 수 없습니다.

적용 시나리오: 공통 특성을 가진 카테고리 또는 항목 그룹.

코드 구현

PHP 코드

<?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):

동작 요청자와 동작 구현자 결합 솔루션 . 군대에서 하는 '경례'와 마찬가지로, 이 명령을 듣는 사람은 누구나 표준적인 경례를 하게 됩니다.

이점: 동작을 쉽게 추가 및 수정하고 여러 명령을 쉽게 집계할 수 있습니다.

단점: 특정 명령 클래스가 너무 많습니다.

적용 시나리오: 조작할 객체에 동일한 조작을 수행합니다.

코드 구현

PHP 코드

<?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. >

내부 구조를 노출하지 않고 집계 개체 콘텐츠에 액세스합니다. 더블 컬러 볼 복권 추첨과 마찬가지로 매번 7개의 볼이 흔들리고, 7개의 볼이 아닌 당첨 번호 조합은 흔들리지 않습니다.

이점: 다양한 방법으로 컬렉션을 탐색합니다.

단점: 전체 컬렉션을 순회할 때마다 요소를 개별적으로 꺼낼 수 없습니다.

적용 시나리오: 컬렉션의 모든 요소가 작동되어야 합니다.

코드 구현

PHP 코드

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


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