浅析命令模式

    对于这种请求-分发式的任务需求,command模式再适合不过了。通过把用户不同请求封装为对象保证了系统单一入口方式,另一方面在增加新任务的时候程序结构会变得清晰简单。现在访问PHP页面的时候,更倾向于提供参数明确告诉系统所要执行的功能,而不是把不同的请求自由分散到不同的PHP子文件中。

    命令模式由几部分组成:命令对象、实例化命令对象的命令工厂(commmand factory)、触发命令对象的控制器(controller)、命令对象的接收者(完成具体的业务逻辑)、部署命令对象的客户端。

    对于传统的任务请求流程大致如下:   
    $params = $_REQUEST['cmd'];//保存参数
    
    $ret = do_task($params);    //任务执行

    echo $ret;                  //反馈结果
    这里主要存在如下几个问题:
1.请求参数没有经过封装直接暴露给业务逻辑层,导致了命令控制层与业务逻辑层紧耦合。
2.命令动作没有经过封装,请求参数和返回结果均被限制了,不利于扩展。

    command模式提供了一个上下文相关的参数类(context),完成了参数传递。不同的命令对象统一从context类取出参数,并把执行结果通过context类返回给上层。

    

context的实现如下:
    class CommandContext{
        private $params = array();        
        private $result = "";        
     
        public function __construct(){
            $params = $_REQUEST;
        }                
        
        public function add_param($key, $value){
            $this->params[$key] = $value;
        }
        
        public function get_param($key){
            $this->params[$key];
        }
        
        public function set_result($result){
            $this->result = $result;
        }
        
        public function get_result(){
            return $this->result;        
        }
    }
command类:
    abstract  class Command(){
        abstract public function execute(CommandContex $context);
    }

    命令对象需要做的工作相对比较简单:取出参数,调用对象处理任务,执行结果返回。

    

前端用户登录命令:
    class LoginCommand extends Command {
        
        public function execute(CommandContext $context){
            
            $ret = true;
            do
            {
                //获取具体处理命令的对象
                $UserManager = Registry::get_user_manager();
                if(!isset($UserManager)){
                    $ret = false;
                    $context->set_error("could not found registry object");
                    break;
                }
                //获取参数
                $username = $context->get_param('username');
                $password = $context->get_param('password');
                //执行操作
                $user = $UserManager->login($username, $password);
                //返回结果        
                if(is_null($user)){
                    $context->set_error($UserManager->error());
                    $ret = false;
                    break;
                } else{
                    $context->add_param('user', $user);
                }
            }while(0);
    
            return $ret;
        }        
    }
    在这里通过静态方法构建命令的接受对象,这样保证了execute接口参数简单化。另外也可以通过把命令接受对象传递给命令对象。

    

接下来实现命令工厂:

    class CommandFactory {
    private static $dir = "commands";
    
    public function get_command($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 Exception('not found command class file');
        }
        require_once($file);        
        if(!class_exists($class)){
            throw new Exception('n
        function triggle(){ot found command class');            
        }
        $cmd = new $class();
        return $cmd;
    }
}
把命令对象文件放在commands文件夹下,根据不同的请求加载不同的命令对象文件,并构建对象。

    

触发命令对象的控制器(controller)的实现:
    
    class Controller{
        
    private $context;

    public function __construct(){
        $context = new CommandContext();
    }    
    
    public function get_context(){
        return $this->context;    
    }    
    
    public function process(){
        $command = CommandFactory::get_command($this->context->get_param('action'));
        if($command->execute($this->context)){
            //ok
        } else {
            //fail
        }
        return;
    }
}
    
最后是部署命令对象的客户端
    class Client{
        function triggle(){
            $controller = new Controller();
            $context = $controller->get_context();
            $context->add_param('action', 'login');
            $context->add_param('username', 'lufy');
            $context->add_param('userpassword', '123456');
            $controller->process();
        }
    }
    The end.

你可能感兴趣的:(PHP,php,命令模式,command)