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

设计模式C++实现(9)——命令模式

2018-01-08 22:50 423 查看


一、简介

         Command命令模式为了解决的问题是:当系统请求繁多复杂时,将请求封装到一个对象(Command)中,并将请求的接受者存放到具体的ConcreteCommand类(Receiver)中,从而实现调用操作的对象和操作的具体实现者之间的解耦。

         Command 模式的典型结构图为:



       Command模式结构图中,将请求的接收者(处理者)放到Command的具体子类ConcreteCommand中,当请求到来时(Invoker 发出Invoke消息激活Command对象),ConcreteCommand将处理请求交给Receiver对象进行处理。


二、详解


1、正常对象参数传递调用

(1)代码reveiver.h:

[html] view
plain copy

#ifndef _RECEIVER_H_  

#define _RECEIVER_H_  

  

class Receiver  

{  

      public:  

          Receiver();  

          ~Receiver();  

          void Action();  

      protected:  

      private:  

};  

  

#endif  

(2)代码reveiver.cpp:

[html] view
plain copy

#include <iostream>  

#include "receiver.h"  

using namespace std;  

  

Receiver::Receiver()  

{  

}  

  

Receiver::~Receiver()  

{  

}  

  

void Receiver::Action()  

{  

       cout<<"---Receiver::Action---"<<endl;  

}  

(3)代码invoker.h:

[html] view
plain copy

#ifndef _INVOKER_H_  

#define _INVOKER_H_  

  

class Command;  

class Invoker  

{  

      public:  

          Invoker(Command *cmd);  

          ~Invoker();  

          void InvokeFunc();  

      protected:  

      private:  

          Command *_cmd;  

};  

  

#endif  

(4)代码invoker.cpp:

[html] view
plain copy

#include <iostream>  

#include "invoker.h"  

#include "command.h"  

using namespace std;  

  

Invoker::Invoker(Command *cmd)  

{  

    _cmd = cmd;  

}  

  

Invoker::~Invoker()  

{  

}  

  

void Invoker::InvokeFunc()  

{  

      cout<<"Invoker::InvokeFunc"<<endl;  

      _cmd->Excute();  

}  

(5)代码command.h:

[html] view
plain copy

#ifndef _COMMAND_H_  

#define _COMMAND_H_  

  

class Receiver;  

class Command  

{  

      public:  

          virtual ~Command();  

          virtual void Excute() = 0;  

      protected:  

          Command();  

      private:  

};  

class ConcreteCommand : public Command  

{  

      public:  

          ConcreteCommand(Receiver *rev);  

          ~ConcreteCommand();  

          void Excute();  

      protected:  

      private:  

          Receiver *_rev;  

};  

  

#endif  

(6)代码command.cpp:

[html] view
plain copy

#include <iostream>  

#include "command.h"  

#include "receiver.h"  

using namespace std;  

  

Command::Command()  

{  

}  

  

Command::~Command()  

{  

}  

  

ConcreteCommand::ConcreteCommand(Receiver *rev)  

{  

      _rev = rev;  

}  

  

ConcreteCommand::~ConcreteCommand()  

{  

}  

  

void ConcreteCommand::Excute()  

{  

      cout<<"ConcreteCommand::Excute"<<endl;  

      _rev->Action();  

}  

(7)代码main.cpp:

[html] view
plain copy

#include <iostream>  

#include "receiver.h"  

#include "invoker.h"  

#include "command.h"  

using namespace std;  

  

int main()  

{  

      //创建具体命令对象cmd并设定它的接收者rev  

      Receiver *rev = new Receiver();  

      Command *cmd = new ConcreteCommand(rev);  

      //请求绑定命令  

      Invoker *inv = new Invoker(cmd);  

      inv->InvokeFunc();  

  

          delete inv;  

          delete cmd;  

          delete rev;  

      return 0;  

}  

(8)代码makefile:

[html] view
plain copy

CFLAGS = -g  

DEFINED = #-D _VERSION  

LIBS =   

CC = g++  

INCLUDES = -I./  

OBJS= main.o receiver.o command.o invoker.o  

TARGET= main  

all:$(TARGET)  

  

$(TARGET):$(OBJS)  

    $(CC) $(CFLAGS) -o $@ $(OBJS)  

  

.SUFFIXES:.o .h  

.SUFFIXES:.cpp .o  

.cpp.o:  

    $(CC) $(DEFINED) -c $(CFLAGS) -o $@ $<  

  

ok:  

    ./$(TARGET)  

clean:  

    rm -f $(OBJS) $(TARGET) core *.log  


2、函数地址回调机制调用

(1)代码receiver.h:

[html] view
plain copy

#ifndef _RECEIVER_H_  

#define _RECEIVER_H_  

  

class Receiver  

{  

      public:  

          Receiver();  

          ~Receiver();  

          void Action();  

      protected:  

      private:  

};  

  

#endif  

(2)代码receiver.cpp:

[html] view
plain copy

#include <iostream>  

#include "receiver.h"  

using namespace std;  

  

Receiver::Receiver()  

{  

}  

  

Receiver::~Receiver()  

{  

}  

  

void Receiver::Action()  

{  

       cout<<"---Receiver::Action---"<<endl;  

}  

(3)代码command.h:

[html] view
plain copy

#ifndef _COMMAND_H_  

#define _COMMAND_H_  

  

class Command  

{  

      public:  

          virtual ~Command(){};  

          virtual void Excute() = 0;  

      protected:  

          Command(){};  

      private:  

};  

  

template <class T>  

class SimpleCommand : public Command  

{  

      public:  

          typedef void (T::*ActionFunc)();  

          SimpleCommand(T *rev, ActionFunc act) {  

              _rev = rev;  

              _act = act;  

          }  

          virtual void Excute() {  

              (_rev->*_act)();     //回调调用方式  

          }  

          ~SimpleCommand() {  

              delete _rev;  

          }  

      protected:  

      private:  

          T *_rev;  

          ActionFunc _act;  

};  

  

#endif  

(4)代码main.cpp:

[html] view
plain copy

#include <iostream>  

#include "command.h"  

#include "receiver.h"  

using namespace std;  

  

int main()  

{  

      Receiver *rev = new Receiver();  

      Command *cmd = new SimpleCommand<Receiver>(rev, &Receiver::Action);  

      cmd->Excute();  

        

      delete cmd;  

      return 0;  

}  

(4)makefile:

[html] view
plain copy

CFLAGS = -g  

DEFINED = #-D _VERSION  

LIBS =   

CC = g++  

INCLUDES = -I./  

OBJS= main.o receiver.o  

TARGET= main  

all:$(TARGET)  

  

$(TARGET):$(OBJS)  

    $(CC) $(CFLAGS) -o $@ $(OBJS)  

  

.SUFFIXES:.o .h  

.SUFFIXES:.cpp .o  

.cpp.o:  

    $(CC) $(DEFINED) -c $(CFLAGS) -o $@ $<  

  

ok:  

    ./$(TARGET)  

clean:  

    rm -f $(OBJS) $(TARGET) core *.log  




3、运行结果

(Centos6.3系统中运行结果:)



      Command模式的实现和思想都很简单,其关键就是将一个请求封装到一个类(Command)中,再提供处理对象(Receiver),最后Command命令由Invoker激活。

       在上述2中用到 C++中的类成员函数指针,将请求接收者的处理抽象出来作为参数传给Command对象,实际也就是回调的机制(Callback)来实现这一点,即将处理操作方法地址(在对象内部)通过参数传递给Command对象,Command在适当的时候(Invoke激活的时候)再调用该函数。


三、总结

(1)Command模式关键就是提供一个抽象的Command类,并将执行操作封装到Command类接口中,Command类中一般就是只是一些接口的集合,并不包含任何的数据属性。

(2)Command模式将调用操作的对象和知道如何实现该操作的对象解耦,在上述结构图中Invoker对象根本就不知道具体的是那个对象在处理Excute操作(当然要知道是Command类别的对象,也仅此而已)。

(3)在Command要增加新的处理对象很容易,可以通过创建新的继承自Command的子类来实现这一点。

(4)Command模式可以和Memento模式结合起来,支持取消的操作。

(5)源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/8437165)。 

本文转自:

http://blog.csdn.net/taiyang1987912/article/details/43567077
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: