【设计模式】行为型模式-Command模式
# 功能
将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。
# 解决
- 主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适
- 何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合
- 如何解决:通过调用者调用接受者执行命令,顺序:调用者→接受者→命令
- 关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口
# 优缺点
- 优点:
- 降低了系统耦合度
- 新的命令可以很容易添加到系统中去
- 缺点:使用命令模式可能会导致某些系统有过多的具体命令类
# 应用场景
- 应用实例:struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command
- 使用场景:认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD
- 注意事项:系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式,见命令模式的扩展
# 简单示例代码部分
Command.h
#ifndef _COMMAND_H_
#define _COMMAND_H_
#include <iostream>
using namespace std;
class Reciever{
public:
Reciever(){}
~Reciever(){}
void Action(){
std::cout<<"Reciever action......."<<std::endl;
}
};
class Command {
public:
virtual ~Command(){}
virtual void Excute() = 0;
protected:
Command(){}
};
class Invoker {
public:
Invoker(Command* cmd){
_cmd=cmd;
}
~Invoker(){}
void Invoke(){}
private:
Command* _cmd;
};
class ConcreteCommand:public Command {
public:
ConcreteCommand(Reciever* rev){
_rev=rev;
}
~ConcreteCommand(){}
void Excute(){}
private:
Reciever* _rev;
};
template <class Reciever>
class SimpleCommand:public Command {
public:
typedef void (Reciever::* Action)();
SimpleCommand(Reciever* rev,Action act){
_rev = rev;
_act = act;
}
virtual void Excute() {
(_rev->* _act)();
}
~SimpleCommand() {
delete _rev;
}
private:
Reciever* _rev;
Action _act;
};
#endif
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
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
main.cpp
#include "Command.h"
#include <iostream>
using namespace std;
int main() {
Reciever* rev = new Reciever();
Command* cmd = new SimpleCommand<Reciever>(rev,&Reciever::Action);
cmd->Excute();
Command* cmd2 = new ConcreteCommand(rev);
Invoker* inv = new Invoker(cmd2);
inv->Invoke();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
编辑 (opens new window)
上次更新: 2022/05/18, 15:47:37