this paper defines the analysis of behavioral patterns in pattern design, mainly explaining template method patterns, policy patterns and command patterns. The content of this article comes from the editing and modification of Internet content, which is convenient for readers to learn. In case of infringement, contact the author for deletion at the first time.
1. Template method mode
Template Method: defines the skeleton of an algorithm in operation, and delays some steps to subclasses. Template Method enables subclasses to redefine some specific steps of the algorithm without changing the structure of the algorithm.
class AbstractClass { public: virtual void PrimitiveOperation1()=0; virtual void PrimitiveOperation2()=0; void TemplateMethod(); virtual ~AbstractClass(){} }; class ConcreteClass1 :public AbstractClass { public: virtual void PrimitiveOperation1(); virtual void PrimitiveOperation2(); ~ConcreteClass1(){} }; class ConcreteClass2 :public AbstractClass { public: virtual void PrimitiveOperation1(); virtual void PrimitiveOperation2(); ~ConcreteClass2(){} }; #include "Template.h" #include <iostream> void AbstractClass::TemplateMethod() { //The template method defines the skeleton of the algorithm PrimitiveOperation1(); PrimitiveOperation2(); } void ConcreteClass1::PrimitiveOperation1() { std::cout << "Algorithm step 1" << std::endl; } void ConcreteClass1::PrimitiveOperation2() { std::cout << "Algorithm step 2" << std::endl; } void ConcreteClass2::PrimitiveOperation1() { std::cout << "Component 1" << std::endl; } void ConcreteClass2::PrimitiveOperation2() { std::cout << "Component 2" << std::endl; } #include "Template.h" int main() { AbstractClass *AC1 = new ConcreteClass1(); AC1->TemplateMethod(); AbstractClass *AC2 = new ConcreteClass2(); AC2->TemplateMethod(); delete AC1; delete AC2; }
template method pattern is the simplest object-oriented behavior pattern, which represents the common interface functions and data stored in the base class. The specific implementation is placed in the subclass, and the parent object is used as much as possible for unified external call planning.
2. Strategy mode
Strategy: define a series of algorithms, encapsulate them one by one, and make them replaceable. This pattern allows the algorithm to vary independently of the customers using it.
#include <iostream> using namespace std; // Define the strategy type typedef enum StrategyType { StrategyA, StrategyB, StrategyC }STRATEGYTYPE; // The abstract strategy class Strategy { public: virtual void AlgorithmInterface() = 0; virtual ~Strategy() = 0; // Thanks for the bug raised by hellowei. Please refer to the comments for details }; Strategy::~Strategy() {} class ConcreteStrategyA : public Strategy { public: void AlgorithmInterface() { cout << "I am from ConcreteStrategyA." << endl; } ~ConcreteStrategyA(){} }; class ConcreteStrategyB : public Strategy { public: void AlgorithmInterface() { cout << "I am from ConcreteStrategyB." << endl; } ~ConcreteStrategyB(){} }; class ConcreteStrategyC : public Strategy { public: void AlgorithmInterface() { cout << "I am from ConcreteStrategyC." << endl; } ~ConcreteStrategyC(){} }; class Context { public: Context(STRATEGYTYPE strategyType) { switch (strategyType) { case StrategyA: pStrategy = new ConcreteStrategyA; break; case StrategyB: pStrategy = new ConcreteStrategyB; break; case StrategyC: pStrategy = new ConcreteStrategyC; break; default: break; } } ~Context() { if (pStrategy) delete pStrategy; } void ContextInterface() { if (pStrategy) pStrategy->AlgorithmInterface(); } private: Strategy *pStrategy; }; int main() { Context *pContext = new Context(StrategyA); pContext->ContextInterface(); if (pContext) delete pContext; }
3. Command mode
Command: encapsulate a request as an object, so that you can parameterize customers with different requests; Queue or log requests, and support revocable operations.
when we go to the restaurant for dinner, we order through the waiter. In fact, we don't know who will cook these dishes and when they will finish them. In the abstract, we are the "menu requester" and the chef is the "menu implementer". The two are loosely coupled. We don't know who is making other requests for these dishes, such as "undo, redo". In fact, this is the Command mode of this article. Encapsulate a request as an object, so that you can parameterize the customer with different requests; Queue or log requests, and support undoable operations. The following implements a simple undo redo function:
first define a Command base class:
class Command { public: Command(void); virtual ~Command(void){}; public: virtual void redo()=0;//redo virtual void undo()=0;//revoke };
with a base class, you can define command subclasses of different meta operations according to task needs. ModifyCommand.h:
//Modify command class class CModifyCommand : public Command { public: CModifyCommand(CBaseShape* shape,const QPointF &ptOffSet); virtual ~CModifyCommand(void); public: virtual void redo(); virtual void undo(); private: CBaseShape* m_shape; QPointF m_ptOffSet; };
ModifyCommand.cpp
#include "ModifyCommand.h" CModifyCommand::CModifyCommand(CBaseShape* shape,const QPointF &ptOffSet ) { m_shape = shape; m_ptOffSet = ptOffSet; } CModifyCommand::~CModifyCommand(void) { } void CModifyCommand::redo() { m_shape->Excute(m_ptOffSet); } void CModifyCommand::undo() { m_shape->Excute(-m_ptOffSet); }
batch command class, batchcommand h:
#include "command.h" #include <vector> using namespace std; //Batch command class class CBatchCommand : public Command { public: CBatchCommand(void); virtual ~CBatchCommand(void); public: //Add subcommand void AddCommand(Command* cmd); //Execute subcommand redo function virtual void redo(); //Execute subcommand Undo function virtual void undo(); private: vector<Command*> m_vecCmds;//Storage subcommand };
BatchCommand.cpp:
#include "BatchCommand.h" CBatchCommand::CBatchCommand(void) { } CBatchCommand::~CBatchCommand(void) { for (int i=0;i<m_vecCmds.size();++i) { if (NULL != m_vecCmds[i]) { delete m_vecCmds[i]; m_vecCmds[i] = NULL; } } m_vecCmds.clear(); } void CBatchCommand::redo() { for (int i=0;i<m_vecCmds.size();++i) { m_vecCmds[i]->redo(); } } void CBatchCommand::undo() { for (int i=0;i<m_vecCmds.size();++i) { m_vecCmds[i]->undo(); } } void CBatchCommand::AddCommand( Command* cmd ) { m_vecCmds.push_back(cmd); }
the command class is defined. We also need a class to manage and store various commands generated by each operation. Commandmanager class, here I use two containers to store commands, one to store undo commands and one to store redo commands. CommandManager.h:
#include "Command.h" #include <vector> using namespace std; //Command management class class CommandManager { public: CommandManager(void); virtual ~CommandManager(void); public: //Store command virtual void StoreCommand(Command* cmd); //Clear all commands virtual void ClearAllCommand(); //Clear redo command virtual void ClearRedoCommand(); //Execute undo command virtual void Undo() = 0; //Execute redo command virtual void Redo() = 0; public: vector<Command*> m_vecRedo; vector<Command*> m_vecUndo; };
CommandManager.cpp:
#include "CommandManager.h" CommandManager::CommandManager(void) { } CommandManager::~CommandManager(void) { } void CommandManager::StoreCommand( Command* cmd ) { m_vecUndo.push_back(cmd); ClearRedoCommand();//When adding a new command, clear the redo command } void CommandManager::ClearAllCommand() { for (int i = 0;i<m_vecRedo.size();++i) { if (NULL != m_vecRedo[i]) { delete m_vecRedo[i]; m_vecRedo[i] = NULL; } } for (int i = 0;i<m_vecUndo.size();++i) { if (NULL != m_vecUndo[i]) { delete m_vecUndo[i]; m_vecUndo[i] = NULL; } } m_vecRedo.clear(); m_vecUndo.clear(); } void CommandManager::ClearRedoCommand() { for (int i = 0;i<m_vecRedo.size();++i) { if (NULL != m_vecRedo[i]) { delete m_vecRedo[i]; m_vecRedo[i] = NULL; } } m_vecRedo.clear(); }
the CommandHistoryManager class is designed as a singleton class for easy calling.
#include "commandmanager.h" class CommandHistoryManager : public CommandManager { public: CommandHistoryManager(void); virtual ~CommandHistoryManager(void); public: static CommandHistoryManager *GetInstance() { if (NULL == m_pCmdHistoryManager) { m_pCmdHistoryManager = new CommandHistoryManager(); } return m_pCmdHistoryManager; } static void ReleaseInstance(); virtual void Undo(); virtual void Redo(); private: static CommandHistoryManager* m_pCmdHistoryManager; };
implement undo() and redo() functions:
#include "CommandHistoryManager.h" CommandHistoryManager * CommandHistoryManager::m_pCmdHistoryManager = NULL; CommandHistoryManager::CommandHistoryManager(void) { } CommandHistoryManager::~CommandHistoryManager(void) { } void CommandHistoryManager::Undo() { if ( m_vecUndo.size() <= 0 ) return; Command* cmd = m_vecUndo.at(m_vecUndo.size()-1); cmd->undo(); m_vecUndo.pop_back(); m_vecRedo.push_back(cmd); } void CommandHistoryManager::Redo() { if ( m_vecRedo.size() <= 0 ) return; Command* cmd = m_vecRedo.at(m_vecRedo.size()-1); cmd->redo(); m_vecRedo.pop_back(); m_vecUndo.push_back(cmd); } void CommandHistoryManager::ReleaseInstance() { if (NULL != m_pCmdHistoryManager) { delete m_pCmdHistoryManager; m_pCmdHistoryManager = NULL; } }
command usage:
//Modify command CModifyCommand *mCmd = new CModifyCommand(this,ptOffset); CommandHistoryManager::GetInstance()->StoreCommand(mCmd); //Batch command CBatchCommand *bCmd = new CBatchCommand(); QList<CMyPointShape*>::iterator it; for (it = m_myPointList.begin();it != m_myPointList.end();++it) { CModifyCommand *mCmd = new CModifyCommand(*it,ptOffset); bCmd->AddCommand(mCmd); } CommandHistoryManager::GetInstance()->StoreCommand(bCmd);
reasonable script code can effectively improve work efficiency and reduce repetitive work.
welcome to Zhiyou software development network platform. Our company customized and developed all kinds of software, mainly focusing on desktop professional software development and plug-in customization development. Desktop software mainly includes text and graphics recognition software, information management software, 3D printing software, video software and other professional graphics and image processing software. The plug-ins include AE plug-ins, AI plug-ins, PS plug-ins, PDF plug-ins, 3DMAX plug-ins and Office plug-ins such as Word and Excel. For details, please consult wechat QQ:312117271, mobile phone: 18928899728, email: anjingzhi_sea@163.com.
Company website: http://www.zhiliaos.com