命令模式c++实现

转自:http://blog.csdn.net/zhangbohtz/article/details/6941377


命令模式c++实现

标签: c++commandclassiteratorstringpair
  858人阅读  评论(0)  收藏  举报

说实话,我现在还没有很好地理解命令模式,我只能结合例子谈谈我现在的认识和理解。

按照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,然后,厨师再执行这些命令,一道菜做好了,也就是完成了这个请求。

通过命令模式,我们可以很好的进行客户端和具体提供服务的对象之间的耦合,就像我们在饭店吃饭,从来没有见过厨师一样,也不用管厨师长得帅不衰,我们见到的只是服务员,只要服务员漂亮热情就行了,即使厨师换了我们都不用知道。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值