Php設計模式:行為型模式(一)

巴扎黑
發布: 2016-11-12 11:47:16
原創
1025 人瀏覽過

在上一篇我們講了結構型模式,結構型模式是討論類別和物件的結構的。總共有7種。而今天我們來介紹一下行為型模式。

 

一、什麼是行為型模式?

行為模式:

        就是描述類別與物件之間的溝通和職責的。簡而言之,就是類別和物件扮演什麼角色,還有怎麼扮演這個角色的問題。

 

二、行為型模式的種類

       大體上分為三個大類:常見模式、已知模式、深度模式方法、模式、中介者模式、狀態模式、職責鏈模式、策略模式

       已知模式包括:備忘錄模式

       深度模式包括:說明模式方法、存取者模式

(Template):

        定義一個操作中的演算法骨架,而將一些實作步驟延遲到子類別中實作。就像一個豆漿機,不管放進去的是紅豆還是黑豆,出來的都是豆漿。

        好處:擴充性佳,封裝不變的程式碼,擴充可變的程式碼。

        弊端:彈性差,且無法改變骨架部分。

        應用場景:一類或一組具有共通性的事物中。

程式碼實作

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、迭代器模式(Iterator): 

3、迭代器模式(Iterator): 就像一個雙色球彩券開獎一樣,每次都是搖出七個球,不能能搖不是七個球的中獎號碼組合。

         好處:以不同方式遍歷一個集合。

         弊端:每次遍歷都是整個集合,不能單獨取出元素。

         應用場景:需要操作集合裡的全部元素。

程式碼實作

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();
登入後複製

相關標籤:
php
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!