|
/*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\ tool_observer.h, A reusable implementation of the observer pattern
/
\ Version: 1.0, 1999-07-02: created
/ 1.1, 2001-05-11: simplified for CodeProject article
\
/ Author: Daniel Lohmann (daniel@losoft.de)
\ http://www.losoft.de/
/
\
/ Please send comments and bugfixes to the above email address.
\
/ This code is provided AS IS, you use it at your own risk!
\ You may use it for whatever you want.
/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
#ifndef __TOOL_OBSERVER_H__
#define __TOOL_OBSERVER_H__
namespace tool {
template<class CLASS, class SUBJECT>
struct ObserverAdapter : public SUBJECT::IObserver
{
typedef typename CLASS object_t;
typedef typename SUBJECT::return_t return_t;
typedef typename SUBJECT::arg1_t arg1_t;
typedef return_t (CLASS::*mfunc_t)(arg1_t);
ObserverAdapter( object_t* pObj = NULL, mfunc_t pmfUpdate = NULL )
: m_pObj( pObj ), m_pmfUpdate( pmfUpdate ) {}
virtual return_t Update( arg1_t arg1 = arg1_t() )
{
return (m_pObj->*m_pmfUpdate)( arg1 );
}
virtual void SetUpdate( object_t* pObj, mfunc_t pmfUpdate )
{
m_pObj = pObj;
m_pmfUpdate = pmfUpdate;
}
object_t* m_pObj;
mfunc_t m_pmfUpdate;
};
template<class OBSERVER_INFO = int, class RETURN = int, class ARG1 = int>
class ISubject
{
public:
typedef typename OBSERVER_INFO observer_info_t;
typedef typename RETURN return_t;
typedef typename ARG1 arg1_t;
struct IObserver
{
typedef typename RETURN return_t;
typedef typename ARG1 arg1_t;
virtual return_t Update( arg1_t ) = 0;
};
virtual bool AttachObserver( IObserver* pObserver, observer_info_t Info) = 0;
virtual bool DetachObserver( IObserver* pObserver ) = 0;
};
template<class OBSERVER_INFO = int, class RETURN = int, class ARG1 = int>
class SimpleSubject : public ISubject< OBSERVER_INFO, RETURN, ARG1 >
{
public:
virtual bool AttachObserver( IObserver* pObserver, observer_info_t Info = observer_info_t() )
{
m_aObservers.push_back( observer_entry_t( pObserver, Info ) );
return true;
}
virtual bool DetachObserver( IObserver* pObserver )
{
clients_t::iterator i = m_aObservers.begin();
for( ; i != m_aObservers.end(); ++i )
if( i->pObserver == pObserver ) {
m_aObservers.erase( i );
return true;
}
return false;
}
virtual void NotifyObserver( arg1_t arg1 = arg1_t() )
{
for( clients_t::iterator i = m_aObservers.begin(); i != m_aObservers.end(); ++i )
i->pObserver->Update( arg1 );
}
protected:
struct observer_entry_t
{
observer_entry_t( IObserver* o, observer_info_t i )
: pObserver( o ), Info( i ) {}
IObserver* pObserver;
observer_info_t Info;
};
typedef std::vector< observer_entry_t > clients_t;
clients_t m_aObservers;
};
}
#endif __TOOL_OBSERVER_H__
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Daniel Lohmann (
daniel@losoft.de) is Assistant Professor at the
Distributed Systems and Operating Systems department at Friedrich-Alexander-University Erlangen-Nuremberg, Germany. His main research topic is the design of a highly customizable and scalable operating system product line for deeply embedded systems using static configuration and aspect-oriented techniques. Before joining Universität Erlangen he worked as a freelance trainer and consultant for NT system programming, advanced C++ programming and OOA/OOD. He is interested in upcoming programming techniques like aspect-oriented programming, generative programming and C++ meta coding and has written some nice and handy tools for Windows NT which you can download at his
web site.