zoukankan      html  css  js  c++  java
  • 设计模式 笔记 命令模式 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);

    }



  • 相关阅读:
    vim使用
    linux下编译openjdk8
    《鸟哥的Linux私房菜》学习笔记(9)——条件判断
    《鸟哥的Linux私房菜》学习笔记(8)——bash脚本编程之变量
    《鸟哥的Linux私房菜》学习笔记(7)——grep及正则表达式
    《鸟哥的Linux私房菜》学习笔记(6)——管道及IO重定向
    《鸟哥的Linux私房菜》学习笔记(5)——权限管理
    《鸟哥的Linux私房菜》学习笔记(4)——用户和组
    《鸟哥的Linux私房菜》学习笔记(0)——磁盘与文件系统管理
    Intellij Idea 创建JavaWeb项目
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983124.html
Copyright © 2011-2022 走看看