ホームページ  >  記事  >  バックエンド開発  >  PHP デザイン パターン: 動作パターン (1)

PHP デザイン パターン: 動作パターン (1)

巴扎黑
巴扎黑オリジナル
2016-11-12 11:47:161020ブラウズ

前の記事では、構造パターンについてクラスとオブジェクトの構造について説明しました。全部で7種類あります。今回は行動パターンをご紹介します。

1. 行動パターンとは何ですか? behavioral Pattern:

私たち自身つまり、クラスとオブジェクトがどのような役割を果たし、その役割をどのように果たしていくかという問題です。

2. 動作パターンの種類

一般的に 3 つのカテゴリに分類されます: 一般的なパターン、既知のパターン、深いパターン

一般的なパターンには、テンプレート メソッド パターン、コマンド パターン、イテレータ パターン、オブザーバー モード、メディエーター モード、ステート モードが含まれます。 、責任の連鎖モード、戦略モード

使用する ' ' ' パターン (テンプレート):

操作でアルゴリズムのスケルトンを定義し、一部の実装手順をサブクラスに延期します。豆乳製造機と同じで、小豆を入れても黒豆を入れても出てくるのは豆乳です。

利点: 優れたスケーラビリティ、変更されていないコードをカプセル化し、可変コードを拡張します。

欠点: 柔軟性が低く、骨格部分を変更することができません。

適用シナリオ: 共通の特性を持つもののカテゴリーまたはグループ内。

コード実装

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. コマンドモード(コマンド):

動作リクエスタは動作実装者から分離されています。軍隊における「敬礼」と同じように、この命令を聞いた人は誰でも標準的な敬礼をするでしょう。

利点: 動作の追加と変更が簡単で、複数のコマンドを簡単に集約できます。

欠点: 特定のコマンド クラスが多すぎます。

応用シナリオ: 操作対象のオブジェクトに対して同じ操作を実行します。


コード実装

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. イテレータパターン(Iterator):

内部構造を公開せずに集合オブジェクトの内容にアクセスします。二色玉の抽選と同じように、毎回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 までご連絡ください。