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

命令模式c++实现

2017-01-09 22:03 302 查看
转自:http://blog.csdn.net/zhangbohtz/article/details/6941377




命令模式c++实现

标签: c++commandclassiteratorstringpair
2011-11-06 20:23 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,然后,厨师再执行这些命令,一道菜做好了,也就是完成了这个请求。

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