命令模式c++实现
2012-08-14 11:24
253 查看
说实话,我现在还没有很好地理解命令模式,我只能结合例子谈谈我现在的认识和理解。
按照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,然后,厨师再执行这些命令,一道菜做好了,也就是完成了这个请求。
通过命令模式,我们可以很好的进行客户端和具体提供服务的对象之间的耦合,就像我们在饭店吃饭,从来没有见过厨师一样,也不用管厨师长得帅不衰,我们见到的只是服务员,只要服务员漂亮热情就行了,即使厨师换了我们都不用知道。
按照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,然后,厨师再执行这些命令,一道菜做好了,也就是完成了这个请求。
通过命令模式,我们可以很好的进行客户端和具体提供服务的对象之间的耦合,就像我们在饭店吃饭,从来没有见过厨师一样,也不用管厨师长得帅不衰,我们见到的只是服务员,只要服务员漂亮热情就行了,即使厨师换了我们都不用知道。
相关文章推荐
- 设计模式之命令模式 及 c++ 实现
- 设计模式--命令模式C++实现
- C++实现Undo和Redo框架(命令模式)
- 我所理解的设计模式(C++实现)——命令模式(Command Pattern)
- 详解设计模式中的Command命令模式及相关C++实现
- 设计模式---命令模式(C++实现)
- 设计模式C++实现十九:命令模式
- 设计模式C++实现(17)——命令模式
- 设计模式-命令模式 C++实现
- 设计模式 --> 命令模式(C++实现)
- 命令模式c++实现
- 我所理解的设计模式(C++实现)——命令模式(Command Pattern)
- 设计模式系列3-----C++实现命令模式(Command Pattern)
- Head First设计模式C++实现--第六章:命令(Command)模式
- 命令模式----C++实现
- 设计模式之命令模式,C++实现
- 设计模式--命令模式 C++实现
- (C++实现)——命令模式(Command Pattern)
- 设计模式--命令实现C++
- 大话设计模式--命令模式 Command -- C++实现实例