I have improved my “Acyclic Visitor with Observer” pattern (here is a link to the old one). Now you can create classes that are derived from two Acyclic visitors, something that was not possible with the previous version. On top of that I have made it less complex to use. On top of that they no longer have generic names (like “INotification”). The coolest thing is the registering. Previously you had to create the objects in the user code and also specify the class that should receive it. Now, it’s simply done when you define the class.
Anyway just compare the code:
The old code
class HelloWorldReceiver : public IReceiver
{
public:
HelloWorldReceiver()
{
m_Translators.push_back( CTranslator<HelloWorldReceiver, WorldNote>() );
m_Translators.push_back( CTranslator<HelloWorldReceiver, HelloNote>() );
}
void Receive(WorldNote* aWorld) { }
void Receive(HelloNote* aHello) { }
};
The new code
class HelloWorldVisitor : public tAcyclicVisitor<HelloWorldVisitor>
public:
HelloWorldVisitor() {
RegisterAVObject<Hello>();
RegisterAVObject<World>();
}
void Receive(Hello* obj) { }
void Receive(World* obj) { }
};
And here is all the code you need to start using it, it’s licensed as I promised in the previous post, but as you can see you all you need to do is keep the license in the code (all 21 lines).
// The MIT License
//
// Copyright (c) 2009 Wouter Lindenhof (http://limegarden.net)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef __ACYCLIC_VISITOR_H__
#define __ACYCLIC_VISITOR_H__
#include <list>
/**
* @brief if set to 1 it will allows the user to combine derived acyclic
* visitors, but this is likely to have a cost because of virtual inheritance.
*/
#define AV_ALLOW_VIRTUAL_INHERITANCE 1
/**
* @brief this is the base object
*/
class AVBaseObject
{
public:
virtual ~AVBaseObject() {}
};
class AcyclicVisitor;
class IAVTranslator
{
public:
virtual const bool Accept(AVBaseObject* object, AcyclicVisitor* visitor) const = 0;
};
class AcyclicVisitor
{
typedef std::list<IAVTranslator*> TransList;
protected:
TransList m_AV_Translators;
public:
virtual ~AcyclicVisitor() {
for( TransList::iterator it = m_AV_Translators.begin(); it != m_AV_Translators.end(); ++it )
delete (*it);
m_AV_Translators.clear();
}
void Visit(AVBaseObject* baseObject)
{
for( TransList::iterator it = m_AV_Translators.begin(); it != m_AV_Translators.end(); ++it )
(*it)->Accept(baseObject, this);
}
};
template <typename V, typename O>
class tAVTranslator : public IAVTranslator
{
public:
const bool Accept(AVBaseObject* object, AcyclicVisitor* visitor) const
{
V* original_visitor = dynamic_cast<V*>(visitor);
O* original_object = dynamic_cast<O*>(object);
if(original_object == 0 || original_visitor == 0) return false;
original_visitor->Receive(original_object);
return true;
}
};
template <typename V>
#if AV_ALLOW_VIRTUAL_INHERITANCE == 1
class tAcyclicVisitor : public virtual AcyclicVisitor
#else
class tAcyclicVisitor : public AcyclicVisitor
#endif
{
protected:
template <typename O> void RegisterAVObject()
{
m_AV_Translators.push_back(new tAVTranslator<V, O>());
}
};
#endif
I have also uploaded the entire example that I have used while testing so that you can some more interesting stuff.
limegarden.net, how do you do it?
You will need to be a bit more specific than that.