Recently, when doing some projects, you often need to use the dynamic registration and acquisition of the class, so that the caller can create a class's instance according to the name, and then call the changed virtual function to complete the function call, similar to establishing a set of database access kits It can be done without modifying the original code without modifying the original code. It is only necessary to create a new class in accordance with certain specifications. This class completes its own registration, the caller obtains the change instance according to the name, The techniques involved include templates, Singletons, Object Factory, the following will be included below and some descriptions:
// ClassRegister.h: interface for the cclassregister class.////
#if! defined (AFX_CLASREGISTER_H__809D89C4_E53F_43CE_8DE4_37248A855CCB_37248A855CCB__ENCLUDED _) # Define AFX_CLASREGISTER_H__809D89C4_E53F_43CE_8DE4_37248A855CCB__INCLUDED_
#ifdef _win32 // This assumes that the compiler used on the Windows platform is VC. Since the STL implementation of VC self-portraits causes //, a large number of warnings occur when using MAP, so turn off this warning #pragma Warning (Disable: 4786) #ENDIF
// Introduce the necessary header file #include
Namespace michael {
/ ** * When the default processing method when the specified object is not found, the default method is to throw an exception * / template
Virtual const char * what () const {return "unknown object type passed to factory.";
const _IdentifierType & getId () {return m_unknownId;} private: _IdentifierType m_unknownId;}; protected: virtual _ClassType * OnUnknownType (const _IdentifierType & id) const {throw Exception (id);}};
/ ** * Here is another common processing method, that is, return null when the object cannot be found, * can be replaced by template parameters, but the following registration and creation macro cannot be used * Need yourself to write code or macro * / template
/ ** * Implementation class * There are four template parameters * The first template parameter is an abstract class * The second template parameter is the type of identifier. Here is a string, that is, the name can be obtained. * The third template parameter is a method of creating an actual object or a visitor. , class _IdentifierType = std :: string, class _ProductCreator = _AbstractClass * (*) (), class _FactoryErrorPolicy = CDefaultFactoryError <_IdentifierType, _AbstractClass >> class CClassFactory: _FactoryErrorPolicy {public: / ** * register for classes * / bool Register (const _IdentifierType & id, _ProductCreator creator) {return m_associations.insert (AssocMap :: value_type (id, creator)) second;.} / ** * unregister * / bool unregister (const _IdentifierType & id) {return m_associations.erase ( ID);} / ** * Create an object instance according to the identifier, return * / _abstractclass * createObject (const _identifiertype & id) const_Assocmap :: const_iterator it = m_associations.find (ID); if ( M_associations.end ()! = it) {return (it-> second) ();} return onunknowntype (id);
/ ** * instance of a class factory object * / static CClassFactory * Instance () {static CClassFactory <_AbstractClass, _IdentifierType, _ProductCreator, _FactoryErrorPolicy> inst; return & inst;} public: typedef std :: map <_IdentifierType, _ProductCreator> AssocMap; AssocMap m_associations;
CcLassFactory ()} cclassfactory (const cclassfactory & other) {} virtual ~ cclassfactory () {} cclassfactory & operator = (const cclassfactory & other) {}}
#ifndef dynamic_register_class
/ ** * Here you try to replace CreateObject below the following macros but have not resolved * / template
/ ** * Define a macro, enhance this macro to the specific implementation class, add a static function to the class * This function creates an instance of the object, two template parameters, respectively, real dynamic registration classes and * abstraction Class * This macro needs to check into the PUBLIC section of the class * / # define dynamic_create_class (cls, abstract) / static abstract * createObject () / {/ return new CLS (); /} / ** * Define a macro auto-completion class Registration * This macro needs to be inserted in the implementation file of the class * / # define simply_dynamic_register_class (abstract, cls, strname) / const bool Bret = michael :: cclassfactory
/ ** * Define a macro to get an object of an object based on the name * / # define simply_create_object (abstract, strname) / michael :: cclassfactory
/ ************************************************** ********************** * * The following two macro roots are the same, but they use another error handling method * // * Returns NULL when you can't recruit, not throwing anomalies / ******************************** ********************************* * ** * Defines a macro auto-completion class Register * This macro needs to be inserted in the implementation file of the class * / # define simply_dynamic_register_class_null (Abstract, CLS, STRNAME) / const bool Bret = michael :: cclassfactory abstract, / std :: string, / Abstract * (*) (*) ), / Michael :: CNULLFACTORYERROR
/ ** * Define a macro can get an object of an object based on the name * / # define simply_create_object_null (abstract, strname) / michael :: cclassfactory Abstract, / std :: string, / abstract * (*) (), / Michael :: CNULLFACTORYERROR
#ENDIF
} #ENDIF //! Defined (AFX_CLASREGISTER_H__809D89C4_E53F_43CE_8DE4_37248A855CCB__INCLUDED_)
The following combination example shows how to use:
Here, an abstract class he defines some ways but there is no implementation. The following example is very simple unable to perform real applications, and the purpose is to explain the dynamic registration method.
// Header Database.h
Class CDATABASE
{
PUBLIC:
Virtual void open () = 0; virtual void close () = 0;
}
// Header OracleDb.h
Class Coracledb: Public CDATABASE
{
PUBLIC:
/ / Here, the CORACLEDB class needs to be dynamically registered and the CreateObject function is implemented inside.
Dynamic_create_class (Coracledb, CDatabase)
Virtual void open ();
Virtual void close ();
}
// Implement file CORACLEDB.CPP
#include "oracledb.h"
// This macro completely registered
SIMPLY_DYNAMIC_REGISTER_CLASS (CDatabase, CORACLEDB, "Oracle")
Void Coracledb :: open ()
{
// some implementation
}
Void Coracledb :: Close ()
{
// some implementation
}
After the code is completed, the real caller can obtain the instance of the class according to the string.
int main ()
{
CDATABASE * PDB = Simply_create_Object (CDatabase, "Oracle");
PDB-> Open ();
PDB-> Close ();
Return 0;
}
When you need to increase your Mysql support, you can implement a MySQL class in accordance with the above Oracle method, and then replace the class name in the main function, no need for any substantive changes, more access to the configuration file or the incoming parameters of the main function. To the database category, the distance is as follows:
INT main (int Argc, char ** argv)
{
IF (argc! = 2)
{
Return -1;
}
CDATABASE * PDB = SIMPLY_CREATE_OBJECT (CDatabase, Argv [1]);
PDB-> Open ();
PDB-> Close ();
Return 0;
}
Dynamic registration and acquisition is achieved, and this part of the code is a complete C standard, not dependent on the MFC and other class libraries, which can play a good role in cross-platform applications, because there are many theories involved, and Hugh, there is no introduction, but only explains how to use, interested friends can look at the knowledge about templates, singletons, object factory. :)
I hope to give you some notices, environmental exchanges, huh, huh.