PHP设计模式之命令模式

命令模式用一句话表示就是说:一个命令一个类。在面向对象程式设计的范畴中,命令模式是一种设计模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;
命令模式一般用于广泛的企业应用,特别促进了控制器(请求和处理)和领域模型(应用逻辑)的分离。
命令模式由 3 部分组成,实例化命令对象的客户端、部署命令对象的调用者和接收命令的接受者。

以用户登录与反馈为例

登录与反馈意见第一版:常规版本

demo1.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
header('Content-Type:text/html; charset=utf-8');

class Login{
private $user = 'admin';
private $pass = '123456';

public function execute($user, $pass){
if($this->user == $user && $this->pass = $pass){
return true;
}
return false;
}
}

class FeedBack{
public function execute($name, $date, $info){
if($name && $date && $info){
return true;
}
return false;
}
}

$login = new Login();
if($login->execute('admin', '123456')){
echo '登录成功!';
}else{
echo '登录失败!';
}

$feedback = new FeedBack();
if($feedback->execute('suse', '2015,5,4', '命令模式')){
echo '反馈成功!';
}else{
echo '反馈失败!';
}

此版本两个类都是独立的,互相没有联系。Login 类主要是验证登录,FeedBack 类主要用于客户的反馈信息。execute 方法用户判断是否登录成功,用户反馈的信息是否正确。

登录与反馈意见第二版:使用命令模式构建

demo2.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?php
header('Content-Type:text/html; charset=utf-8');

class Login{
private $user = 'admin';
private $pass = '123456';

public function execute(Context $context){
if($this->user == $context->getParam('user') && $this->pass = $context->getParam('pass')){
return true;
}
return false;
}
}

class FeedBack{
public function execute(Context $context){
if($context->getParam('name') && $context->getParam('date') && $context->getParam('info')){
return true;
}
return false;
}
}

class Context{
private $params = [];
private $succ;
private $error;

public function getSucc(){
return $this->succ;
}

public function setSucc($succ){
$this->succ = $succ;
}

public function getError(){
return $this->error;
}

public function setError($error){
$this->error = $error;
}

public function addParam($key, $value){
$this->params[$key] = $value;
}

public function getParam($key){
return $this->params[$key];
}
}

class Factory{
static public function getCommand($action){
return new $action;
}
}

class Controller{
private $context;

public function __construct(){
$this->context = new Context();
}

public function getContext(){
return $this->context;
}

public function process(){
$cmd = Factory::getCommand($this->context->getParam('action'));
if($cmd->execute($this->context)){
return $this->context->getSucc();
}else{
return $this->context->getError();
}
}
}

$controller = new Controller();
$context = $controller->getContext();
$context->addParam('action', 'Login');
$context->addParam('user', 'admin');
$context->addParam('pass', '123456');
$context->setSucc('登录成功!');
$context->setError('登录失败!');
echo $controller->process();

echo '<br />';
$controller = new Controller();
$context = $controller->getContext();
$context->addParam('action', 'Feedback');
$context->addParam('name', 'suse');
$context->addParam('date', '2015,5,4');
$context->addParam('info', '命令模式');
$context->setSucc('反馈成功!');
$context->setError('反馈失败!');
echo $controller->process();

此版本看上去比第一版复杂很多,但如果系统变的庞大的时候,命令模式则会越来越体现出它的优势,比如实例化对象,调用,提交接收的冗余被大大压缩。

命令模式的三个组成部分别为:

  1. 实例化命令对象类:Factory.class.php (其实就是一个简单工厂)
  2. 部署命令对象的调用者类:Controller.class.php (一个控制器,MVC 会涉及到)
  3. 接收命令的接受者类:Context.class.php (一个模型,Model