深入PHP面向对象、模式与实践——执行及描述任务(5)

来源:互联网 发布:现货原油分析软件 编辑:程序博客网 时间:2024/05/29 07:33

命令模式

创建可被保存和传送的命令对象。

命令模式有助于系统更好进行组织,并有助于扩展。

命令对象的接口极为简单,因为他只要求实现一个方法execute()。命令模式有三部分组成:实例化命令对象的客户端(client)、部署命令对象的调用者(invoker)和接受命令对象的接收者(receiver)。

让我们创建一个具体的Command类:

abstract class Command{    abstract function execute(CommandContext $context);}class LoginCommand extends Command{    function execute(CommandContext $context)    {        $manager = Registry::getAccessManager();        $user = $context->get('username');        $pass = $context->get('pass');        $user_obj = $manager->login($user, $pass);        if (is_null($user_obj)) {            $context->setError($manager->getError());            return false;        }        $context->addParam("user", $user_obj);        return true;    }}

LoginCommand被设计为与AccessManager(访问管理器)对象一起工作。AccessManager是一个虚构出来的类,它的任务就是处理用户登录系统的具体细节。

下面是一个简单的CommandContext实现:

class CommandContext{    private $params = array();    private $error = "";    function __construct()    {        $this->params = $_REQUEST;    }    function addParam($key, $val)    {        $this->params[$key] = $val;    }    function get($key)    {        return $this->params[$key];    }    function setError($error)    {        $this->error = $error;    }    function getError()    {        return $this->error;    }}

现在我们仍然缺少客户端代码(即用于创建命令对象的类)及调用者类(使用生成的命令的类)。

class CommandNotFoundException extends Exception{}class CommandFactory{    private static $dir = 'commands';    static function getCommand($action = 'Default')    {        if (preg_match('/\W/', $action)) {            throw new Exception("illegal characters in action");        }        $class = UCFirst(strtolower($action)) . "Command";        $file = self::$dir . DIRECTORY_SEPARATOR . "{$class}.php";        if (!file_exists($file)) {            throw new CommandNotFoundException("could not find '$file'");        }        require_once($file);        if (!class_exists($class)) {            throw new CommandNotFoundException("no '$class' class located");        }        $cmd = new $class();        return $cmd;    }}

CommandFactory类在commands目录里查找特定的类文件。
下面是一个简单的调用者:

class Controller{    private $context;    function __construct()    {        $this->context = new CommandContext();    }    function getContext()    {        return $this->context;    }    function process()    {        $cmd = CommandFactory::getCommand($this->context->get('action'));        if (!$cmd->execute($this->context)) {            //处理失败        } else {            //成功            //现在分发视图        }    }}$controller = new Controller();//伪造用户请求$context = $controller->getContext();$context->addParam('action', 'login');$context->addParam('username', 'bob');$context->addParam('pass', 'tiddles');$controller->process();

让我们再创建一个Command类:

class FeedbackCommand extends Command{    function execute(CommandContext $context)    {        $msgSystem = Registry::getMessageSystem();        $email = $context->get('email');        $msg = $context->get('msg');        $topic = $context->get('topic');        $result = $msgSystem->send($email, $msg, $topic);        if (!$result) {            $context->setError($msgSystem->getError());            return false;        }        return true;    }}

下图展示命令模式的各个部分:
这里写图片描述

1 0