Php设计模式:行为型模式(一)

来源:互联网 发布:自动连接移动数据 编辑:程序博客网 时间:2024/06/11 20:09

   

原文详见:http://www.ucai.cn/blogdetail/7023?mid=1&f=5

 可以在线运行查看效果哦!    

    

        

         在上一篇我们讲了结构型模式,结构型模式是讨论类和对象的结构的。总共有7种。而今天我们来介绍一下行为型模式。


一、什么是行为型模式?

行为型模式:

        就是描述类和对象之间的通信和职责的。简而言之,就是类和对象扮演什么角色,还有怎么扮演这个角色的问题。


二、行为型模式的种类

       大体上分为三个大类:常见模式、已知模式、深度模式

       常见模式包括: 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、状态模式、职责链模式、策略模式

       已知模式包括:备忘录模式

       深度模式包括:解释器模式、访问者模式


常见模式

1、模版方法模式(Template):

        定义一个操作中的算法骨架,而将一些实现步骤延迟到子类当中实现。就像一个豆浆机,不管放进去的是红豆还是黑豆,出来的都是豆浆。

        好处:扩展性好,封装不变的代码,扩展可变的代码。

        弊端:灵活性差,不能改变骨架部分。

        应用场景:一类或一组具有共性的事物中。

代码实现

<?php/** * 优才网公开课示例代码 * * 模板方法模式 Template * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */function output($string) {    echo    $string . "\n";}class Request {    public $token = '';    public function __construct() {        $this->token    = '0c6b7289f5334ed2b697dd461eaf9812';    }}class Response {    public function render($content) {        output(sprintf('response-render: %s', $content));    }    public function redirect($uri) {        output(sprintf('response-redirect: %s', $uri));    }    public function json($data) {        output(sprintf('response-data: %s', json_encode($data)));    }} //父类,抽象类abstract class Controller{    //封装了输入输出    protected $request;    protected $response;    //返回数据    protected $data = 'data';    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 (empty($_SESSION['auth'])){            //没登录就直接跳转了,不再执行后续的操作            $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('title' => 'ucai');    }    //覆盖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/** * 优才网公开课示例代码 * * 命令模式 Command * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */function output($string) {    echo    $string . "\n";}class Document {    private $name = '';    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 = '';    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('A');        $graphics       = new Graphics('B');        $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 = '';    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 = '';    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('A'));        array_push($array, new Document('B'));        array_push($array, new Graphics('C'));        array_push($array, new Graphics('D'));                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 = '';    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 = '';    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 = '';    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 = '';    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('A')));        array_push($array, new DocumentCommand(new Document('B')));        array_push($array, new GraphicsCommand(new Graphics('C')));        array_push($array, new GraphicsCommand(new Graphics('D')));                foreach ($array as $command) {            $command->execute();        }        $top            = array_pop($array);        $top->undo();    }}Client::test();

3、迭代器模式(Iterator):

         访问聚合对象内容而不暴露内部结构。就像一个双色球彩票开奖一样,每次都是摇出七个球,不能能摇不是七个球的中奖号码组合。

         好处:以不同方式遍历一个集合。

         弊端:每次遍历都是整个集合,不能单独取出元素。

         应用场景:需要操作集合里的全部元素。

代码实现

<?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('id' => '1'),                        1 => array('id' => '2'),                        2 => array('id' => '3'),                        3 => array('id' => '4'),                    );        //        $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('Key[%d],Val[%s]', $key, json_encode($val)));        }        output(sprintf('MaxPage[%d]', $pager->getMaxPage()));        output(sprintf('Prev[%d]', $pager->getPrevPage()));        output(sprintf('Next[%d]', $pager->getNextPage()));        $iterator       = $pager->getIterator();        while($iterator->valid()){            print_r($iterator->current());            $iterator->next();        }        $iterator->rewind();    }        }    Client::test(); 

优才网免费公开课请戳这里:http://www.ucai.cn/course5/



0 0