您的位置:首页 > 编程语言 > C语言/C++

命令模式c++实现

2011-11-06 20:23 295 查看
说实话,我现在还没有很好地理解命令模式,我只能结合例子谈谈我现在的认识和理解。

按照GoF的解释,命令模式是将一个请求封装成一个对象的方式,在过程型编程语言中,我们通常用一个回调函数来表示一个请求,这样,客户端在调用这个函数的时候,必须要知道这个函数的一些信息,这样就产生了耦合。为了解耦,我们采用命令模式,在客户端和具体的提供服务的对象之间添加了一层,也就是Invoker,它会负责将来自客户端的请求委托给具体的提供服务的对象,这样,客户端无需知道提供服务的具体事那个一个对象,而提供服务的对象也无需知道她所服务的对象是谁。这样讲还是有些抽象,我们来看一个实际的例子。

// Command.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include

#include

#include

#include

using namespace std;

// 抽象的命令类

// 我们利用这个类,将我们的请求封装成对象

// 这个类的execute()也就是执行任务完成这个请求

class ICommand

{

public:

virtual void execute( int n ) = 0;

};

// 具体的命令类,满足不同的请求

// 这里,我们使用不同的符号个数表示输入的数值

class BarCommand : public ICommand

{

public:

virtual void execute( int n )

{

for( int i = 0; i < n; ++i )

cout<<"█";

cout< };

};

class StarCommand : public ICommand

{

public:

virtual void execute( int n )

{

for( int i = 0; i < n; ++i )

cout<<"★";

cout< };

};

// 客户端和提供服务的命令之间的桥梁

// 客户端向Invoker提出请求,Invoker将请求委派给具体的请求对象

class Invoker

{

public:

// 向Inboker添加命令,也就是Invoker能够接收的请求

void addCommand(string strName, ICommand* pComm)

{

m_mapCommands.insert(

make_pair>(strName,

shared_ptr(pComm) ));

};

// 接收请求,并将请求委派给具体的对象去执行

// 这里,Inboker并不知道具体执行的是哪一个Command

void request( string strName, int nNum )

{

map>::iterator it;

it = m_mapCommands.find( strName );

if( m_mapCommands.end() != it )

{

it->second->execute( nNum );

}

}

private:

// 菜单

map> m_mapCommands;

};

// 模拟客户端的情况

int _tmain(int argc, _TCHAR* argv[])

{

// 将具体的Command添加到invoker中

// 也就是组织所谓的菜单

Invoker invoker;

invoker.addCommand("Star", new StarCommand());

invoker.addCommand("Bar", new BarCommand());

// 向Invoker提出请求,Invoker将请求委派给具体的Command

invoker.request("Bar", 8);

invoker.request("Star",7);

return 0;

}

通过命令模式,通过在客户端和具体的命令之间添加一层Invoker,剪断了客户端和具体服务提供者之间的耦合,降低了两者之间的耦合度,同时也增加了灵活性,比如我们可以灵活的某一个请求的服务提供者,通过单独的服务提供者Command类,可以很方便的提供redo和undo的功能等等,这些都是命令模式的优势。

我这样的解释可能还是难以理解,我们再来看一个现实中的Command模式的例子。例如,我们在饭店点菜吃饭就是一个很好的命令模式的例子。在这个场景中,有这样几个角色:

顾客:Client,也就是我们的客户端

服务员:Invoker,她负责处理来自客户端的请求并将其封装成命令Command

订单:Order,Command,这就是Invoker所封装的请求

厨师:Cook,receiver,这就是最终处理请求的服务提供者,很多时候,receiver和Command合并在了一起。

当顾客向服务员点菜,整个饭店所能够提供的服务,也即是能够做的菜都在菜单上,例如我们例子中的m_maoCommands(服务员Invoker当然是知道什么才可以有,什么菜不可以有的),顾客的请求都在菜单这个范围内,顾客将这些请求进行组合向服务员点菜,服务员将顾客的这个请求写到订单上,这样就封装成了一个个的命令Command,然后,厨师再执行这些命令,一道菜做好了,也就是完成了这个请求。

通过命令模式,我们可以很好的进行客户端和具体提供服务的对象之间的耦合,就像我们在饭店吃饭,从来没有见过厨师一样,也不用管厨师长得帅不衰,我们见到的只是服务员,只要服务员漂亮热情就行了,即使厨师换了我们都不用知道。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: