Self-Registering Objects in C++ by Jim Beveridge Listing One (a) enum file_types { TYPE_UNKNOWN, TYPE_JPEG, TYPE_TIFF, TYPE_GIF }; int find_extension_type(char *ext) { if (strcmp(ext, ".JPG") == 0) return TYPE_JPEG; if (strcmp(ext, ".TIF") == 0) return TYPE_TIFF; if (strcmp(ext, ".GIF") == 0) return TYPE_GIF; return TYPE_UNKNOWN; } (b) int type = find_extension_type(extension); switch(type) { case TYPE_JPEG: import_jpeg(filename); break; case TYPE_TIFF: import_tiff(filename); break; case TYPE_GIF: import_gif(filename); break; } Listing Two (a) ConversionObject* CreateConversionObject(char *ext) { if (strcmp(ext, ".JPG") == 0) return new JpegFileConverter; if (strcmp(ext, ".TIF") == 0) return new TifFileConverter; if (strcmp(ext, ".GIF") == 0) return new GifFileConverter; return NULL; } (b) ConversionObject* pConverter = CreateConversionObject(extension); if (pConverter) pConverter->Import(filename); delete pConverter; Listing Three class FileConverterProxyBase { public: FileConverterProxyBase(); virtual FileConverter* CreateObject() const = 0; // Expose criteria here virtual char* GetExtension() const = 0; virtual bool IsCompressed() const = 0; }; FileConverterProxyBase::FileConverterProxyBase() { gConverterStore.Register(this); } Listing Four template class FileConverterProxy : public FileConverterProxyBase { FileConverter* CreateObject() const { return new T; } // Member functions in T are static virtual char* GetExtension() const { return T::GetExtension(); } virtual bool IsCompressed() const { return T::IsCompressed(); } }; Listing Five class TiffFileConverter : public FileConverter { public: virtual void Import(const char *filename); virtual void Export(const char *filename); // These are the criteria support functions static char* GetExtension() { return ".tif"; } static bool IsCompressed() { return TRUE; } }; FileConverterProxy gTiffProxy; Listing Six // Definition FileConverter* FileConverterStore::CreateByExtension( const char* ext) { for (unsigned i=0; i< m_pConverters->size(); i++) if (stricmp( m_pConverters->at(i)->GetExtension(), ext ) == 0) return m_pConverters->at(i)->CreateObject(); return NULL; } // Usage void SomeFunc() { FileConverter* pConverter; pConverter = gConverterStore.CreateByExtension(".TIF"); if (pConverter) pConverter->Import("Image.TIF"); delete pConverter; }