-
-
Save lexich/3014072 to your computer and use it in GitHub Desktop.
DI (Dependency Injection) Singlton
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __SN_H_ | |
#define __SN_H_ | |
// \author Ефремов Алексей (lexich) | |
/* | |
//Описание Snc технологии | |
//IBeanInterface.h | |
struct IBeanInterface{ | |
enum{ | |
sncInit = 0, //Обязательное обьявление данной константы | |
sncSecond, | |
}; | |
virtual ~IBeanInterface(){} | |
virtual void setFoo( int ) = 0; | |
virtual int foo() const = 0; | |
}; | |
//IBeanInterface.cpp | |
#include "IBeanInterface.h" | |
#include <sn.h> | |
class BeanInterface1 : public IBeanInterface{ | |
public: | |
BeanInterface1() : data( 0 ) {} | |
virtual void setFoo( int val ){ data = val; } | |
virtual int foo() const { return data; } | |
int data; | |
}; | |
SN_BEAN_IMPL_DEFAULT( IBeanInterface, BeanInterface1 ) | |
class BeanInterface2 : public IBeanInterface{ | |
public: | |
BeanInterface2() : data2( 0 ) {} | |
virtual void setFoo( int val ){ data2 = val; } | |
virtual int foo() const { return data2; } | |
int data2; | |
}; | |
SN_BEAN_IMPL( IBeanInterface, BeanInterface2, IBeanInterface::sncSecond ) | |
//main.cpp | |
#include "IBeanInterface.h" | |
#include <sn.h> | |
#include <assert.h> | |
struct TestClass { | |
Sn<IBeanInterface> bean; | |
Mo<IBeanInterface> obean; | |
}; | |
void main(){ | |
//Режим работы синглтона | |
const int a1 = 1; | |
const int a2 = 2; | |
const int o1 = 3; | |
const int o2 = 4; | |
{ | |
Sn<IBeanInterface> bean; | |
bean->setFoo(a1); //BeanInterface1::setFoo(int); | |
bean.init<IBeanInterface::sncSecond>(); | |
bean->setFoo(a2); //BeanInterface2::setFoo(int); | |
} | |
{ | |
Sn<IBeanInterface> bean2; | |
assert( bean2->foo() == a1 ); //BeanInterface1::foo() | |
bean2.init<IBeanInterface::sncSecond>(); | |
assert( bean2->foo() == a2 ); //BeanInterface2::foo() | |
} | |
{ | |
bool bState1 = Snc<IBeanInterface,IBeanInterface::sncInit >::instance()->foo() == a1; | |
bool bState2 = Snc<IBeanInterface,IBeanInterface::sncSecond>::instance()->foo() == a2; | |
assert( bState1 ); | |
assert( bState2 ); | |
} | |
{ | |
TestClass p; | |
assert( p.bean->foo() == a1 ); | |
p.obean->setFoo( o1 ); | |
assert( p.obean->foo() == o1 ); | |
p.bean.init<IBeanInterface::sncSecond>(); | |
p.obean.init<IBeanInterface::sncSecond>(); | |
p.bean->setFoo(a2); | |
p.obean->setFoo(o2); | |
TestClass p1 = p; | |
assert( p.bean.get() ); | |
assert( !p.obean.get() );//destructive copy | |
assert( p1.bean.get() ); | |
assert( p1.obean.get() ); | |
assert( p1.bean->foo() == a2 ); | |
assert( p1.obean->foo() == o2 ); | |
p1.bean.init<IBeanInterface::sncInit>(); | |
p1.obean.init<IBeanInterface::sncInit>(); | |
assert( p1.bean->foo() == a1 ); | |
assert( p1.obean->foo() == o1 ); | |
} | |
//Режим работы контейнера объекта | |
{ | |
Mo<IBeanInterface> obean; | |
obean->setFoo( o1 ); | |
obean.init<IBeanInterface::sncSecond>(); | |
obean->setFoo( o2 ); | |
obean.init<IBeanInterface::sncInit>(); | |
assert( obean->foo() == o1 ); | |
obean.init<IBeanInterface::sncSecond>(); | |
assert( obean->foo() == o2 ); | |
} // Экземпляр BeanInterface1 и BeanInterface2 разрушается | |
//Ограничения | |
//запрешено копирование обьектов Snc<> Sn<> Mo<> | |
//Sn<> Snc<>(false)- cинглтон (не разрушает объект при уничтожении) | |
//Mo<> Snc<>(true)- контейнер объектов (разрушает объект при уничтожении) | |
{ | |
Sn<IBeanInterface> bean; | |
IBeanInterface* p1 = bean.get(); | |
const IBeanInterface* p2 = bean.get(); | |
const Sn<IBeanInterface> bean1; | |
bean1->foo(); | |
} | |
} | |
*/ | |
#include <list> | |
#include <map> | |
#define SN_BEAN_FUNC_IMPL( BeanInterface, NUM, init_functor ) \ | |
namespace work_tools{ \ | |
namespace ex{ \ | |
template<> \ | |
BeanInterface* Creator<BeanInterface,NUM>::instance(){ \ | |
return static_cast<BeanInterface*>(init_functor()); \ | |
} \ | |
} \ | |
} \ | |
#define SN_BEAN_IMPL( BeanInterface, BeanClass, NUM ) \ | |
namespace work_tools{ \ | |
namespace ex{ \ | |
template<> \ | |
BeanInterface* Creator<BeanInterface,NUM>::instance(){ \ | |
BeanClass* beanItem = new BeanClass(); \ | |
return static_cast<BeanInterface*>( beanItem ); \ | |
} \ | |
} \ | |
} \ | |
#define SN_BEAN_IMPL_DEFAULT(BeanInterface, BeanClass) \ | |
SN_BEAN_IMPL(BeanInterface, BeanClass, BeanInterface::sncInit ) \ | |
#define SN_BEAN_INIT(BeanInterface, NUM) \ | |
namespace work_tools{ \ | |
namespace ex{ \ | |
const static IRegistrator* _autoreg##BeanInterface \ | |
= Registrator::get( Creator<BeanInterface,NUM>::create_call ); \ | |
} \ | |
} \ | |
#define SN_BEAN_INIT_DEFAULT( BeanInterface ) \ | |
SN_BEAN_INIT( BeanInterface, BeanInterface::sncInit ) \ | |
#define SN_BEAN_IMPL_INIT( BeanInterface, BeanClass, NUM ) \ | |
SN_BEAN_IMPL( BeanInterface, BeanClass, NUM ) \ | |
SN_BEAN_INIT( BeanInterface, NUM ) \ | |
#define SN_BEAN_IMPL_DEFAULT_INIT( BeanInterface, BeanClass ) \ | |
SN_BEAN_IMPL_DEFAULT( BeanInterface, BeanClass ) \ | |
SN_BEAN_INIT_DEFAULT( BeanInterface ) \ | |
namespace work_tools{ | |
namespace ex{ | |
typedef void(*reg_func)(void); | |
class Reg{ | |
public: | |
Reg():bExec(false){} | |
public: | |
void exec(){ | |
if( !bExec ){ | |
bExec = true; | |
for( std::list<reg_func>::iterator it = lst.begin(); it != lst.end(); ++it ) | |
(*it)(); | |
} | |
} | |
void add( reg_func ptr ){ | |
lst.push_back(ptr); | |
} | |
bool bExec; | |
std::list<reg_func> lst; | |
}; | |
struct IRegistrator{}; | |
class Registrator : public IRegistrator{ | |
Registrator(){} | |
public: | |
static Registrator* get(){ | |
static Registrator st; | |
return &st; | |
} | |
static Registrator* get(reg_func foo){ | |
Registrator::get()->reg.add(foo); | |
return Registrator::get(); | |
} | |
static void exec(){ | |
Registrator::get()->reg.exec(); | |
} | |
Reg reg; | |
}; | |
}//ex | |
}//work_tools | |
namespace work_tools{ | |
namespace ex{ | |
template< typename T, int TRealize > | |
class Creator{ | |
T* instance(); | |
public: | |
static void create_call(){ create(); } | |
static T* create( bool bNewInstance = false ){ | |
static Creator creator; | |
if( !bNewInstance ){ | |
if( !creator.self ){ | |
creator.self = creator.instance(); | |
} | |
return creator.self; | |
} | |
else { | |
return creator.instance(); | |
} | |
} | |
~Creator(){ | |
if( self ){ delete self; self = 0; } | |
} | |
private: | |
Creator() : self(0){} | |
Creator ( const Creator& ); | |
const Creator& operator=( const Creator& ); | |
private: | |
T* self; | |
}; | |
}//ex | |
}//work_tools | |
template< typename T, int TBaseRealize > | |
class Snc{ | |
typedef std::map<int,T*> Container; | |
typedef typename Container::iterator Iter; | |
public: | |
/** | |
* \fn static T* Snc::instance() | |
* | |
* \brief Режим синглтон. | |
* | |
* \author Lexich | |
* \date 21.07.2011 | |
* | |
* \return Указатель на статический объект. | |
*/ | |
static T* instance(){ | |
Snc<T,TBaseRealize> st( false ); | |
return st.get(); | |
} | |
Snc( bool bNewInstance ) | |
: m_nType(TBaseRealize) | |
, data(0) | |
, m_bNewInstance( bNewInstance ) | |
, m_bNull( false ){} | |
~Snc() | |
{ | |
for ( Iter it = m_mapCache.begin(); | |
it != m_mapCache.end(); ++it ) | |
{ delete (*it).second; } | |
data = 0; | |
} | |
/** | |
* \fn int Snc::getType() const | |
* | |
* \brief Получить идентификатор экземпляра. | |
* | |
* \author Lexich | |
* \date 21.07.2011 | |
* | |
* \return Идентификатор экземпляра. | |
*/ | |
int getType() const { return m_nType; } | |
/** | |
* \fn T* Snc::operator->() | |
* | |
* \brief Возвращает экземпляр обьекта. | |
* | |
* \author Lexich | |
* \date 21.07.2011 | |
* | |
* \return Экземпляр обьекта. | |
*/ | |
T* operator->(){ return get(); } | |
/** | |
* \fn T* Snc::operator->() const | |
* | |
* \brief Возвращает экземпляр обьекта. | |
* | |
* \author Lexich | |
* \date 21.07.2011 | |
* | |
* \return Экземпляр обьекта. | |
*/ | |
T* operator->() const { return get(); } | |
/** | |
* \fn T* Snc::get() const | |
* | |
* \brief Возвращает экземпляр обьекта. | |
* | |
* \author Lexich | |
* \date 21.07.2011 | |
* | |
* \return Экземпляр обьекта. | |
*/ | |
T* get() const { return data ? data : init<TBaseRealize>(); } | |
/** | |
* \fn template< int TRealize > T* Snc::init() | |
* | |
* \brief Инициализация указателя | |
* согласно идентификатора. | |
* | |
* \author Lexich | |
* \date 21.07.2011 | |
* | |
* \return Указатель на экземпляр объекта. | |
*/ | |
template< int TRealize > | |
T* init() const{ | |
m_nType = TRealize; | |
if( m_bNewInstance && m_bNull ) return 0; | |
if( m_bNewInstance ){ | |
Iter it = m_mapCache.find(TRealize); | |
if( it != m_mapCache.end() ){ | |
data = (*it).second; | |
return data; | |
} | |
} | |
data = work_tools::ex::Creator<T,TRealize>::create(m_bNewInstance); | |
if( m_bNewInstance ) | |
m_mapCache[ TRealize ] = data; | |
return data; | |
} | |
protected: | |
mutable Container m_mapCache; | |
mutable int m_nType; | |
mutable T* data; | |
mutable bool m_bNewInstance; | |
mutable bool m_bNull; | |
protected: | |
void clear() const{ | |
if( !m_bNewInstance ) return; | |
m_bNull = true; | |
m_mapCache.clear(); | |
data = 0; | |
} | |
public: | |
Snc(const Snc &it){ | |
m_nType = it.m_nType; | |
data = it.data; | |
m_bNull = false; | |
m_bNewInstance = it.m_bNewInstance; | |
m_mapCache = it.m_mapCache; | |
it.clear(); | |
} | |
Snc &operator=(const Snc &it){ | |
m_nType = it.m_nType; | |
data = it.data; | |
m_bNull = false; | |
m_bNewInstance = it.m_bNewInstance; | |
m_mapCache = it.m_mapCache; | |
it.clear(); | |
return *this; | |
} | |
}; | |
/** | |
* \class | |
* | |
* \brief Синглтон. | |
* | |
* \author Lexich | |
* \date 21.07.2011 | |
*/ | |
template< typename T > | |
class Sn : public Snc<T, T::sncInit >{ | |
public: | |
Sn() : Snc<T, T::sncInit >(false){} | |
}; | |
/** | |
* \class | |
* | |
* \brief Sn хранитель объекта | |
* Реализует деструктивное копирование. | |
* | |
* \author Lexich | |
* \date 21.07.2011 | |
*/ | |
template< typename T > | |
class Mo : public Snc<T, T::sncInit >{ | |
public: | |
Mo() : Snc<T, T::sncInit >(true){} | |
private: | |
//Копирование | |
static T* instance(); | |
}; | |
#endif//__SN_H_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Развитие идеи http://habrahabr.ru/post/116577/