Design Patterns 19--Command Patterns (Command Patterns) -- Behavioral Patterns

By encapsulating the request into an object (Command) and storing the recipient of the request in a specific ConcreteCommand class (Receiver), the Command pattern decouples the object invoking the operation from the specific implementer of the operation.

 

 

In the structure diagram of Command mode, the receiver (processor) of the request is placed in ConcreteCommand, a specific subclass of Command. When the request arrives (Invoker sends an Invoke message to activate the Command object), ConcreteCommand handles the request to the Receiver object for processing.

#pragma once
//Reciever.h
class Reciever 
{ 
public: 
	Reciever();
	~Reciever(); 
	void Action(); 
protected: 
private:
};
//Reciever.cpp 
#include "stdafx.h"
#include "Reciever.h" 
#include <iostream>
Reciever::Reciever()
{ 
} 
Reciever::~Reciever() 
{ 
} 
void Reciever::Action() 
{ 
	std::cout<<"Reciever action......."<<std::endl; 
}

#pragma once
//Command.h
class Reciever; 
class Command 
{ 
public: 
	virtual ~Command();
	virtual void Excute() = 0;
protected: 
	Command(); 
private:
}; 
class ConcreteCommand:public Command
{ 
public: 
	ConcreteCommand(Reciever* rev);
	~ConcreteCommand(); 
	void Excute(); 
protected: 
private: 
	Reciever* _rev; 
};

//Command.cpp 
#include "stdafx.h"
#include "Command.h" 
#include "Reciever.h" 
#include <iostream>
Command::Command() 
{ 
} 
Command::~Command() 
{ 
} 
void Command::Excute() 
{ 
} 
ConcreteCommand::ConcreteCommand(Reciever* rev)
{ 
	this->_rev = rev;
} 
ConcreteCommand::~ConcreteCommand() 
{ 
	delete this->_rev; 
} 
void ConcreteCommand::Excute() 
{ 
	_rev->Action(); 
	std::cout<<"ConcreteCommand..."<<std::endl; 
}

#pragma once
//Invoker.h
class Command; 
class Invoker 
{ 
public: 
	Invoker(Command* cmd); 
	~Invoker();
	void Invoke(); 
protected: 
private: 
	Command* _cmd; 
};

//Invoker.cpp 
#include "stdafx.h"
#include "Invoker.h" 
#include "Command.h" 
#include <iostream>
Invoker::Invoker(Command* cmd) 
{ 
	_cmd = cmd; 
} 
Invoker::~Invoker() 
{ 
	delete _cmd; 
} 
void Invoker::Invoke() 
{ 
	_cmd->Excute(); 
}

int main(int argc, _TCHAR* argv[])
{
	Reciever* rev = new Reciever();
	Command* cmd = new ConcreteCommand(rev); 
	Invoker* inv = new Invoker(cmd); 
	inv->Invoke();
	return 0;
}

The implementation and idea of the Command pattern are very simple. The key is to encapsulate a request into a class (Command), then provide a processing object (Receiver), and finally the Command command is activated by Invoke r. In addition, we can abstract the processing of the request recipient and pass it to the Command object as a parameter, which is actually called back mechanism. That is to say, the address of the processing operation method (inside the object) is passed to the Command object by parameters, and the Command object is in the right time (I). The function is called again when nvoke is activated. Here we will use the concept of class member function pointer in C++. In order to facilitate learning, a simple source code is given for reference.

#pragma once
//Reciever.h
class Reciever 
{ 
public: 
	Reciever();
	~Reciever(); 
	void Action(); 
protected: 
private:
};

//Reciever.cpp 
#include "stdafx.h"
#include "Reciever.h" 
#include <iostream>
Reciever::Reciever()
{ 
} 
Reciever::~Reciever() 
{ 
} 
void Reciever::Action() 
{ 
	std::cout<<"Reciever action......."<<std::endl; 
}


#pragma once
//Command.h
class Reciever; 
class Command 
{ 
public: 
	virtual ~Command();
	virtual void Excute() = 0;
protected: 
	Command(); 
private:
}; 

////////////////////////////2
template <class Reciever> 
class SimpleCommand:public Command 
{ 
public: 
	typedef void (Reciever::* Action)(); 
	SimpleCommand(Reciever* rev,Action act) 
	{ 
		_rev = rev; 
		_act = act; 
	} 
	virtual void Excute() 
	{ 
		(_rev->* _act)(); 
	} 
	~SimpleCommand() 
	{ 
		delete _rev; 
	} 
protected: 
private: 
	Reciever* _rev; 
	Action _act; 
};

int main(int argc, _TCHAR* argv[])
{
	Reciever* rev2 = new Reciever();
	Command* cmd2 = new SimpleCommand<Reciever>(rev2,&Reciever::Action); 
	cmd2->Excute();
	return 0;
}

Note that the above template is used to parameterize the recipient of the request for a simple demonstration, of course. In complex situations, we provide an abstract Command object and then create subclasses of Command to support more complex processing.

 

 

The idea of Command mode is very simple, but Command mode is also very common and powerful. In fact, the key to the Command pattern is to provide an abstract Command class and encapsulate execution operations into the Command class interface, which is generally just a collection of interfaces and does not contain any data attributes (of course, in the sample code, our Command class has a Receive for processing operations). The reference to the R class, but its function is only to implement the Excute interface of this Command. This method is the most despised design method by pure object-oriented designers, just like when OO novices do system design, just using Class as a keyword and encapsulating C global functions to find a class is considered to be the completion of object-oriented design.

But things in the world are not absolute. The above-mentioned approach may be an immature manifestation in most OO designs, but it works well in the Command model. The main manifestations are as follows:

1) Command mode decouples the object that invokes the operation and the object that knows how to implement the operation. In the structure diagram of Command above, the Invoker object doesn't know exactly which object is dealing with Excute operations (of course, Command class objects, that's all).

2) It's easy to add new processing objects to Command. We can do this by creating new subclasses inherited from Command.

3) Command mode can be combined with Memento mode to support cancellation.

Added by robcrozier on Thu, 15 Aug 2019 11:28:39 +0300