设计模式 笔记 命令模式 Command


//---------------------------15/04/25----------------------------


//Conmmand  命令模式----对象行为型模式


/*

    1:意图:

        将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,

        以及支持可撤销的操作。

    2:别名:

        ActionTransaction(事务)

    3:动机:

    4:适用性:

        1>抽象出待执行的动作以参数化某对象。可以使用回调函数表达这种参数化机制。

          也就是说,Conmmand模式是回调机制的一个面向对象的代替品。

        2>在不同的时刻指定、排列和执行请求。一个Conmmand对象可以有一个与初始请求无关的生存期。

          如果请求的接收者可以用一种与地址空间无关的方式表达,那么就可以将负责该请求的命令对象

          传送给另一个不同的进程,并在那儿实现该请求。

        3>支持取消操作。执行操作后,可以调用一个接口来取消操作。

        4>支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。

        5>用构建在原语操作上的高层操作构造一个系统。

    5:结构:

        Client               Invoker------->Command:

         |  |                               Execute()

            |                                   |

         |  |                               ConcreteCommand:

            |------->Receiver:<-------------receiver

         |           Action()               Execute()

                                            { receiver->Action();}

         |- - - - - - - - - - - - - - - - ->state

    6:参与者:

        1>Command

            声明执行操作的接口。

        2>ConcreteCommand

            1)将一个接收者对象绑定于一个动作。

            2)调用接收者相应的操作,以实现Execute

        3>Client

            创建一个具体命令对象并设定它的接受者。

        4>Invoker

            要求该命令执行这个请求。

        5>Receiver

            知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接受者。

    7:协作:

        1>Client创建一个ConcreteCommand对象并指定它的Receiver对象。

        2>Invoker对象存储该ConcreteCommand对象。

        3>Invoker通过调用Conmmand对象的Execute操作来提交一个请求。若该命令时可撤销的,

          ConcreteCommand就在执行Execute操作之前存储当前状态以用于取消该命令。

        4>ConcreteCommand对象调用它的Receiver的一些操作以执行该请求。

    8:效果:

        1>Command模式将调用操作的对象与指导如何实现该操作的对象解耦。

        2>Command是头等的对象。它们可以像其他的对象一样被操作和扩展。

        3>你可讲多个命令装配成一个复合命令。

        4>增加新的Command很容易,因为这无需改变已有的类。

    9:实现:

        1>一个命令对象应达到何种智能程度:

            命令对象的能力可大可小。一个极端是只确定接收者和执行该请求的动作。另一个极端是自己

            实现所有功能,根本不需要额外的接收者对象。(这样就退化成策略模式了)

        2>支持取消和重做

            如果Command提供方法逆转他们操作的执行(例如UnexecuteUndo操作),就可以支持取消和重做

            功能。为了达到这个目的ConcreteCommand类需要存储额外的状态信息:

                1)接收者对象,它真正执行处理该请求的各操作。

                2)接收者执行操作的参数。

                3)如果处理请求的操作会改变接收者对象中的某些值,那么这些值夜必须先存储起来。接收者

                  还必须提供一些操作,以使该命令可将接收者恢复到它先前的状态。

        3>避免取消操作过程中的错误积累

            使用Menmento模式来让Command访问信息时不暴露其他对象的内部信息。

        4>使用C++模版

            不能取消 并且 不需要参数的命令,可以使用C++模版实现,这样可以避免为每一种动作和接收者

            都创建一个Command子类。                                                         

    10:代码示例:                                                                        */


//abstract Command

class Command

{

public:

    virtual ~Command();

    virtual void Execute() = 0;

protected:

    Command();

};


//ConcreteCommand

class OpenCommand : public Command

{

public:

    OpenCommand(Application*);

    virtual void Execute();

    

protected:

    virtual const char* AskUser();

private:

    Application* _application;

    char* _response;

};



OpenCommand::OpenCommand(Application* a)

{

    _application = a;

}


//先请求一个名字,然后添加文件,然后打开之

void OpenCommand::Execute()

{

    const char* name = AskUser();

    if(name != 0)

    {

        Document* document = new Document(name);

        _application->Add(document);

        document->Open();

    }

}


//ConcreteCommand

class PasteCommand : public Command

{

public:

    PasteCommand(Document*);

    virtual void Execute();

    

private:

    Document* _document;

};


PasteCommand::PasteCommand(Document* doc)

{

    _document = doc;

}


void PasteCommand::Execute()

{

    _document->Paste();

}


//ConcreteCommand:通过模版实现,避免多余的子类。

template<class Receiver>

class SimpleCommand : public Command

{

public:

    //创建一个别名:这是一个函数指针,一个参数为空,返回为空的Receiver类的成员函数指针

    //也是因为这个命令不需要参数,所以可以声明成模版类。

    typedef void (Receiver::* Action)();

    SimpleCommand(Receiver* r, Action a): _receiver(r), _action(a){}

    virtual void Execute();

    

private:

    Action _action;

    Receiver* _receiver;

};


template<class Receiver>

void SimpleCommand<Receiver>::Execute()

{

    (_receiver->*_action)();

}


MyClass* Receiver = new MyClass;

//...

Command* aCommand = new SimpleCommand<MyClass>(receiver, &MyClass::Action);

//...

aCommand->Execute();


//ConcreteCommand:一次执行多条命令的复合命令

class MarroCommand : public Command

{

public:

    MarroCommand();

    virtual ~MarroCommand();

    

    virtual void Add(Command*);

    virtual void Remove(Command*);

    

    virtual void Execute();

    

private:

    List<Command*>* _cmds;

};


void MarroCommand::Execute()

{

    ListIterator<Command*> i(_cmds);

    for(i.First(); !i.IsDone(); i.Next())

    {

        Command* c = i.CurrentItem();

        c->Execute();

    }

}


void MarroCommand::Add(Command* c)

{

    _cmds->Append(c);

}


void MarroCommand::Remove(Command* c)

{

    _cmds->Remove(c);

}



转载于:https://www.cnblogs.com/boydfd/p/4983124.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值