Skip to content

Instantly share code, notes, and snippets.

@lexich
Created June 28, 2012 21:34
Show Gist options
  • Save lexich/3014072 to your computer and use it in GitHub Desktop.
Save lexich/3014072 to your computer and use it in GitHub Desktop.
DI (Dependency Injection) Singlton
#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_
@lexich
Copy link
Author

lexich commented Jun 28, 2012

Развитие идеи http://habrahabr.ru/post/116577/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment