设计模式笔记-Command命令模式

命令模式:将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。该模式实现了 请求和实现 的解耦,实现手段就是将请求抽象为一个对象。

一般的实现基本都是上面定义的前半段,请求的排队和记录,以及撤销(undo),恢复(redo)操作都可以在ConcreteCommand里实现。这时候,可以在ConcreteCommand里保存一些状态信息!


举个遥控器-电视机的例子,这里的Receiver就相当于电视吧,因为它执行命令嘛,发送命令的Invoker就相当于遥控器!

真正执行命令的接口函数都在Receiver类里,每一个ConcreteCommand类都相当于一个具体的命令,里面都放有一个Receiver类指针,只是在各自的Execute()函数里,调用的是Receiver类里不同的执行命令的函数,所以用户在使用时,通过具体的ConcreteCommand类指针来操作就行了。这里又加了一层Invoker类,它可以进行一些命令组织的操作,呈现给用户统一的接口,如果你想用什么命令,直接ConcreteCommand* cmd->Execute(),也行啊,但这样比较乱啊!

看代码吧:

class ReceiverTV {
public:
	void actionOpen() {
		cout<<"Open"<<endl;
	}
	void actionClose() {
		cout << "Close" << endl;
	}
	void actionChange() {
		cout << "Change" << endl;
	}
};
class ICommand {
public:
	virtual void execute()=0;
protected:
	ReceiverTV * recvTV;
};

class OpenCommand :public ICommand {
public:
	OpenCommand(ReceiverTV*);
	void execute();
};

class CloseCommand :public ICommand {
public:
	CloseCommand(ReceiverTV*);
	void execute();
};

class ChangeCommand :public ICommand {
public:
	ChangeCommand(ReceiverTV*);
	void execute();
};
OpenCommand::OpenCommand(ReceiverTV* recv)
{
	recvTV = recv;
}
void OpenCommand::execute()
{
	recvTV->actionOpen();
}

CloseCommand::CloseCommand(ReceiverTV* recv)
{
	recvTV = recv;
}
void CloseCommand::execute()
{
	recvTV->actionClose();
}

ChangeCommand::ChangeCommand(ReceiverTV* recv)
{
	recvTV = recv;
}
void ChangeCommand::execute()
{
	recvTV->actionChange();
}
class Invoker {
public:
	enum CMD { OPEN, CLOSE, CHANGE };
public:
	void addCommand(CMD e, ICommand *cmd) {
		mapCommand[e] = cmd;
	}
	void runCommand(CMD e) {
		mapCommand[e]->execute();
	}
private:
	map<CMD, ICommand*> mapCommand;
};

int main()
{
	ReceiverTV* recv = new ReceiverTV();
	ICommand * open = new OpenCommand(recv);
	ICommand * close = new CloseCommand(recv);
	ICommand * change = new ChangeCommand(recv);
	Invoker *invoker = new Invoker();
	invoker->addCommand(Invoker::OPEN, open);
	invoker->addCommand(Invoker::CLOSE, close);
	invoker->addCommand(Invoker::CHANGE, change);

	invoker->runCommand(Invoker::OPEN);
	invoker->runCommand(Invoker::CLOSE);
	invoker->runCommand(Invoker::CHANGE);
	return 0;
}
认真看一下很容易看懂,但在我心里不服务的地方就是这个Invoker类,它的实现也决定了用户(main函数)怎么用。我这里是用一个map把遥控器所有的3个命令都保存起来了,以后用户用的时候直接通过枚举参数调用runCommand函数就行了。想法是参照了 这一篇,但也有别的各种实现,比如:不用map,而用vector或list等,不加区分地把命令指针保存起来,这样,命令要执行的话会全部执行,这就是Command+Composite模式;还有,也可以在Invoker里只保存一个ICommand*变量,传递进来哪个命令我就执行哪个,这样用户代码任务就增加了。各有各的使用场景,大家根据自己的需求选择。我这种实现我觉得对该例子来说合理一些,不过看着也是别扭!

贴一个Command+Composite的UML图,代码区别不大,略!



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值