当前位置:编程学习 > C/C++ >>

command pattern -- 命令模式

在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如需要对行为进行“记录、撤销/重做(undo/redo)、事务”等处理,这种无法抵御变化的紧耦合是不合适的。Command设计模式就是在这种情况下,将“行为请求者”与“行为实现者”解耦,将一组行为抽象为对象,以实现二者之间的松耦合。
“Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.” – GoF
将一个请求封装为一个对象,从而可用不同的请求(一个被封装成了对象的请求)对客户程序(即调用者)进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。www.zzzyk.com
 
实例分析,实际工作中,我们遇到了很多文档,都支持回退/前进的功能,它们快捷键也是惊人的相似Ctrl+z与Ctrl+y。下面将用一段代码来实现其操作,其原理就是命令模式。
[cpp]  www.zzzyk.com
#include <iostream>  
#include <stack>  
  
class Receiver  
{  
    private:  
        std::string str;  
    public:  
        std::string get_str(){ return str; }  
        void set_str(const std::string& s){ str=s; }  
        void append(std::string astr){ str.append(astr); }  
        void show(){ std::cout<<str<<std::endl; }  
};  
  
class Command  
{  
    public:  
        virtual void execute()=0;  
        Command(Receiver *re,const std::string& p)  
        :r(re),par(p)  
        {}  
        virtual ~Command(){}  
    protected:  
        Receiver * r;  
        std::string par;  
};  
  
class UndoCommand:public Command  
{  
    public:  
        UndoCommand(Receiver *re,const std::string& p)  
        :Command(re,p)  
        {}  
        virtual void undo()=0;  
        virtual void redo()=0;  
        virtual ~UndoCommand(){}  
};  
  
class ConcreteCommand:public UndoCommand  
{  
    public:  
        ConcreteCommand(Receiver *re,const std::string& p)  
        :UndoCommand(re,p)  
        {}  
        void execute()  
        {  
            preStr=r->get_str();  
            r->append(par);  
            curStr=r->get_str();  
        }  
  
        void undo()  
        {  
            r->set_str(preStr);  
        }  
  
        void redo()  
        {  
            r->set_str(curStr);  
        }  
    private:  
        std::string preStr;  
        std::string curStr;  
          
};   
  
class ConcreteManager  
{  
    private:  
        std::stack<Command*> exeComStack;  
        std::stack<Command*> undoComStack;  
    public:  
        void executeCommand(Command* cmd);  
        void undoCommand();  
        void redoCommand();  
        ~ConcreteManager();  
};  
ConcreteManager::~ConcreteManager()  
{  
    while(exeComStack.size()>0)  
    {  
        delete exeComStack.top();  
        exeComStack.pop();  
    }  
    while(undoComStack.size()>0)  
    {  
        delete undoComStack.top();  
        undoComStack.pop();  
    }  
}  
  
void ConcreteManager::executeCommand(Command* cmd)  
{  
    cmd->execute();  
    exeComStack.push(cmd);  
}  
  
void ConcreteManager::undoCommand()  
{  
    if(exeComStack.size()>0)  
    {  
        UndoCommand *cmd =dynamic_cast<UndoCommand*>(exeComStack.top());  
        exeComStack.pop();  
        cmd->undo();  
        undoComStack.push(cmd);  
    }  
}  
  
void ConcreteManager::redoCommand()  
{  
    if(undoComStack.size()>0)  
    {  
        UndoCommand * cmd=dynamic_cast<UndoCommand*>(undoComStack.top());  
        undoComStack.pop();  
        cmd->redo();  
        exeComStack.push(cmd);  
    }  
}  
  
int main(int argc,char** argv)  
{  
    ConcreteManager *co=new ConcreteManager;  
    Receiver* re=new Receiver;  
    Command* cm1=new ConcreteCommand(re,"hu");  
    Command* cm2=new ConcreteCommand(re,"cs");  
    Command* cm3=new ConcreteCommand(re,"dn");  
    Command* cm4=new ConcreteCommand(re,"!!");   
    co->executeCommand(cm1);  
    co->executeCommand(cm2);  
    co->executeCommand(cm3);  
    co->executeCommand(cm4);  
    re->show();  
    co->undoCom
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,