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

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

[php]  view plain copy 浅析PHP命令模式_封装 浅析PHP命令模式_php_02
  1. 对于传统的任务请求流程大致如下:     
  2. $params = $_REQUEST['cmd'];//保存参数  
  3.   
  4. $ret = do_task($params);    //任务执行  
  5.   
  6. echo $ret;                  //反馈结果  
    这里主要存在如下几个问题:
1.请求参数没有经过封装直接暴露给业务逻辑层,导致了命令控制层与业务逻辑层紧耦合。
2.命令动作没有经过封装,请求参数和返回结果均被限制了,不利于扩展。

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

    

[php]  view plain copy 浅析PHP命令模式_封装 浅析PHP命令模式_php_02
  1. context的实现如下:  
  2.     class CommandContext{  
  3.         private $params = array();          
  4.         private $result = "";          
  5.        
  6.         public function __construct(){  
  7.             $params = $_REQUEST;  
  8.         }                  
  9.           
  10.         public function add_param($key$value){  
  11.             $this->params[$key] = $value;  
  12.         }  
  13.           
  14.         public function get_param($key){  
  15.             $this->params[$key];  
  16.         }  
  17.           
  18.         public function set_result($result){  
  19.             $this->result = $result;  
  20.         }  
  21.           
  22.         public function get_result(){  
  23.             return $this->result;          
  24.         }  
  25.     }  
[php]  view plain copy 浅析PHP命令模式_封装 浅析PHP命令模式_php_02
  1. command类:  
  2.     abstract  class Command(){  
  3.         abstract public function execute(CommandContex $context);  
  4.     }  

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

    

[php]  view plain copy 浅析PHP命令模式_封装 浅析PHP命令模式_php_02
  1. 前端用户登录命令:  
  2.     class LoginCommand extends Command {  
  3.           
  4.         public function execute(CommandContext $context){  
  5.               
  6.             $ret = true;  
  7.             do  
  8.             {  
  9.                 //获取具体处理命令的对象  
  10.                 $UserManager = Registry::get_user_manager();  
  11.                 if(!isset($UserManager)){  
  12.                     $ret = false;  
  13.                     $context->set_error("could not found registry object");  
  14.                     break;  
  15.                 }  
  16.                 //获取参数  
  17.                 $username = $context->get_param('username');  
  18.                 $password = $context->get_param('password');  
  19.                 //执行操作  
  20.                 $user = $UserManager->login($username$password);  
  21.                 //返回结果          
  22.                 if(is_null($user)){  
  23.                     $context->set_error($UserManager->error());  
  24.                     $ret = false;  
  25.                     break;  
  26.                 } else{  
  27.                     $context->add_param('user'$user);  
  28.                 }  
  29.             }while(0);  
  30.       
  31.             return $ret;  
  32.         }          
  33.     }  
    在这里通过静态方法构建命令的接受对象,这样保证了execute接口参数简单化。另外也可以通过把命令接受对象传递给命令对象。

    

[php]  view plain copy 浅析PHP命令模式_封装 浅析PHP命令模式_php_02
  1. 接下来实现命令工厂:  
  2.   
  3.     class CommandFactory {  
  4.     private static $dir = "commands";  
  5.       
  6.     public function get_command($action="Default"){  
  7.         if(preg_match('/\W/'$action)) {  
  8.             throw new Exception('illegal characters in action');  
  9.         }  
  10.         $class = UCFirst(strtolower($action))."Command";  
  11.         $file = self::$dir . DIRECTORY_SEPARATOR."{$class}.php";  
  12.         if(!file_exists($file)){  
  13.             throw new Exception('not found command class file');  
  14.         }  
  15.         require_once($file);          
  16.         if(!class_exists($class)){  
  17.             throw new Exception('n  
  18.         function triggle(){ot found command class');              
  19.         }  
  20.         $cmd = new $class();  
  21.         return $cmd;  
  22.     }  
  23. }  
把命令对象文件放在commands文件夹下,根据不同的请求加载不同的命令对象文件,并构建对象。

    

[php]  view plain copy 浅析PHP命令模式_封装 浅析PHP命令模式_php_02
  1. 触发命令对象的控制器(controller)的实现:  
  2.       
  3.     class Controller{  
  4.           
  5.     private $context;  
  6.   
  7.     public function __construct(){  
  8.         $context = new CommandContext();  
  9.     }      
  10.       
  11.     public function get_context(){  
  12.         return $this->context;      
  13.     }      
  14.       
  15.     public function process(){  
  16.         $command = CommandFactory::get_command($this->context->get_param('action'));  
  17.         if($command->execute($this->context)){  
  18.             //ok  
  19.         } else {  
  20.             //fail  
  21.         }  
  22.         return;  
  23.     }  
  24. }  
    
[php]  view plain copy 浅析PHP命令模式_封装 浅析PHP命令模式_php_02
  1. 最后是部署命令对象的客户端  
  2.     class Client{  
  3.         function triggle(){  
  4.             $controller = new Controller();  
  5.             $context = $controller->get_context();  
  6.             $context->add_param('action''login');  
  7.             $context->add_param('username''lufy');  
  8.             $context->add_param('userpassword''123456');  
  9.             $controller->process();  
  10.         }  
  11.     }  
    The end.