设计模式探秘-12-命令模式

命令模式的学习与实践

命令模式

命令模式是一个高内聚的模式,将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

类图

  1. Receive接受者角色,执行命令的角色
  2. Command命令角色,需要执行的所有命令都在这里申明
  3. Invoker调用者角色,接受到命令,并执行命令

命令模式简单,封装性非常好,将请求方和执行方分开,扩展性有了保障,通用代码简单。

优点

  1. 类间解偶,调用者和接收者角色之间没有任何依赖关系,调用者实现功能只需调用Command抽象类的execute方法,不需要了解是那个接收者。
  2. 可扩展性,Command的子类容易扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
  3. 命令模式结合其他模式会更优秀,命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少Command子类的膨胀问题。

缺点

Command的子类,如果由N个命令,Command的子类会有N个,该类会膨胀的非常大。

使用场景

在出现命令的地方都可以使用命令模式。

注意事项

扩展

实践

简单实现

在实际应用中可以有多个Reciever,将Reciever封装在Command中,不对Client暴露,并在Command中维护队列,将多个事件按队列依次执行。

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
#include <iostream>

using namespace std;

//命令模式
class Reciever
{
public:
Reciever() {};
virtual ~Reciever() {};
virtual void Action() = 0;
};

class RecieverA : public Reciever
{
public:
RecieverA() {};
virtual ~RecieverA() {};
void Action()
{
cout<<__FUNCTION__<<" A"<<endl;
}
};

class RecieverB : public Reciever
{
public:
RecieverB() {};
virtual ~RecieverB() {};
void Action()
{
cout<<__FUNCTION__<<" B"<<endl;
}
};


class Command
{
public:
virtual ~Command() {};
virtual void Excute() = 0;
protected:
Command(){};
};

class ConcreteCommand : public Command
{
public:
ConcreteCommand(Reciever *rec)
{
m_pRev = rec;
}
~ConcreteCommand()
{
delete m_pRev;
}
void Excute()
{
m_pRev->Action();
cout<<__FUNCTION__<<endl;
}
private:
Reciever *m_pRev;
};

class Invoker
{
public:
Invoker(Command* cmd)
{
m_pCmd = cmd;
}
~Invoker()
{
delete m_pCmd;
}
void Invoke()
{
m_pCmd->Excute();
}
private:
Command *m_pCmd;
};

int main()
{
Reciever *reva = new RecieverA();
Command *cmda = new ConcreteCommand(reva);
Invoker *inva = new Invoker(cmda);
inva->Invoke();
Reciever *revb = new RecieverB();
Command *cmdb = new ConcreteCommand(revb);
Invoker *invb = new Invoker(cmdb);
invb->Invoke();

return 0;
}

参考资料

  1. 设计模式之禅
  2. GoF+23种设计模式解析