对于这种请求-分发式的任务需求,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;
- }
- }
- 接下来实现命令工厂:
- 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;
- }
- }
- 触发命令对象的控制器(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();
- }
- }