Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / C++

Observing the world - how to build a reuseable implementation of a design pattern

Rate me:
Please Sign up or sign in to vote.
4.58/5 (11 votes)
11 Jun 200111 min read 94.1K   397   86  
An article about the techniques to pour reusable design (a design pattern) into reusable code with an example of the observer pattern.
/*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\ 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Germany Germany
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.

Comments and Discussions