本文是学习刘伟技术博客和《设计模式-可复用面向对象软件的基础》笔记,博客链接:http://blog.csdn.net/lovelion/article/details/17517213
主要是对博客和书本做提炼和记录,更多是对设计模式的基础框架学习,细节将略去,侧重对每个设计模式框架的理解。
我应该理解和掌握的:
1)能够画出这个设计模式的架构框图;
2)能够根据架构框图写出对应的伪代码;
3)这个模式的应用场景,主要优缺点。
1.命令模式
现实生活中,最直观的命令模式例子便是开关灯,开关是一个发送请求者,接收者是电灯泡,电线可以看做是一个命令;这便是一个命令模式的流程;发送者按下开关,它本身根本不需要知道开的是哪个电器,我们也可以把电线接到日光灯,替换原有的灯泡。所以把接有不同电器的电线接到开关,这样开关与电线连接的电器就不存在直接的耦合关系。命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接的引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。
(1)定义
命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。别名又称动作模式或事务模式。
1)命名模式结构图
核心在于引入了命令类,通过它来降低发送者和接收者的耦合度,请求发送者只需指定一个命令对象,再通过命令对象来调用请求接收者的处理方法。
2)参与者
a) Command(抽象命令类):声明执行操作的借口;
b) ConcreteCommand(具体命令类):将一个接收者对象绑定于一个动作;调用接收者相应的操作,以实现Execute();
c) Client(客户端):创建一个具体命令并设定他的接收者,绑定到调用者。
d) Invoker(调用者):要求该命令执行这个请求。注入的是抽象命令类,客户端程序通过嵌入不同的具体命令类即可。
e) Receiver(接收者):接收者执行与请求相关的操作,任何类都可能作为一个接收者。
3)看图写程序
/*
** FileName : CommandPattern
** Author : lin005
** Date : 2015/02/01
** Description : More information, please go to http://blog.csdn.net/amd123456789
*/
//接收者
class Receive
{
public:
void action()//接收者方法
{
cout<<"Receive Actioin()"<<endl;
}
};
//抽象命令类
class Command
{
public:
virtual void execute() = 0;//声明操作接口
};
//调用者,类似我所说的开关
class Invoker
{
public:
Invoker(Command* command):c(command){}
void call()
{
c->execute();
}
private:
Command* c;//注入抽象命令类,通过它来调用接收者,骑到耦合的作用
};
//具体命令对象,把它注入给调用者
class ConcreteCommand:public Command
{
public:
ConcreteCommand(Receive* rc):r(rc){}
void execute()
{
r->action();
}
private:
Receive* r;//注入接收者,最后调用它来执行操作。
};
//客户端编程
int main(int argc, const char * argv[]) {
//接收者
Receive* r = new Receive();
//命令
Command* c = new ConcreteCommand(r);
//调用者
Invoker* i = new Invoker(c);
i->call();
return 0;
}
4)命令队列
将多个请求排队,当一个请求发送者发送一个请求时,将不止一个请求接收者产生相应,这些请求接收者将逐个执行业务方法,完成对请求的处理。其实我的理解是,基本原理不变,对上面进行扩展而已,所以还是得通过最基本的结构图,进行扩展去理解其他的实现。
//声明一个命令队列类,存储所有具体命令对象
//调用者注入命令队列对象
class CommandQueue
{
public:
void addCommand(Command* c)
{
commandList.push_back(c);
};
void removeCommand(Command* c)
{
//业务实现
};
void execute()
{
//对队列进行遍历,执行业务方法
}
private:
vector<Command*> commandList;
};
(2)总结
1)优点
a) 降低系统的耦合度,将调用操作的对象与知道如何实现该操作的对象解耦。
b) 增加新的Command很容易,因为无需改变已有的类。
c) 你可以将多个命令装配成一个复合命令。比如命令队列。
2)缺点
a) 针对每一个对请求接收者的调用操作都需要设计一个具体命令类,使用命令模式可能会导致过多的具体命令类。
(3)使用场景
1)系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
2)系统需要在不同的时刻指定、排列、执行请求。一个Command对象可以有一个和初始请求无关的生存期。
3)支持命令的撤销和恢复操作。Command的Execute操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。Command接口必须添加一个UnExecute()操作,该操作取消上一次Execute调用的结果,执行的命令被存储在一个历史列表中,通过向前和向后遍历这一列表分别来调用Execute和UnExecute实现重数不限的取消和重做。