- Single-serving visitor pattern
In
computer programming , the single-serving visitor pattern is a design pattern. Its intent is to optimise the implementation of a visitor that is allocated, used only once, and then deleted (which is the case of most visitors).Applicability
The single-serving visitor pattern should be used when visitors do not need to remain in memory. This is often the case when visiting a hierarchy of objects (such as when the
visitor pattern is used together with thecomposite pattern ) to perform a single task on it, for example counting the number of cameras in a 3D scene.The regular
visitor pattern should be used when the visitor must remain in memory. This occurs when the visitor is configured with a number of parameters that must be kept in memory for a later use of the visitor (for example, for storing the rendering options of a 3D scene renderer).However, if there should be only one instance of such a visitor in a whole program, it can be a good idea to implement it both as a single-serving visitor and as a singleton. In doing so, it is ensured that the single-serving visitor can be called later with its parameters unchanged (in this particular case "single-serving visitor" is an abuse of language since the visitor can be used several times).
Usage examples
The single-serving visitor is called through the intermediate of static methods.
* Without parameters:
Element* elem; SingleServingVisitor::applyTo(elem);
* With parameters:
Element* elem; TYPE param1, param2; SingleServingVisitor::applyTo(elem, param1, param2);
* Implementation as a singleton:
Element* elem; TYPE param1, param2; SingleServingVisitor::setParam1(param1); SingleServingVisitor::setParam2(param2); SingleServingVisitor::applyTo(elem);
Consequences
Pros
* "No "zombie" objects". With a single-serving visitor, it is ensured that visitors are allocated when needed and destroyed once useless.
* "A simpler interface than visitor". The visitor is created, used and free by the sole call of the "applyTo" static method.Cons
* "Repeated allocation". At each call of the "applyTo" method, a single-serving visitor is created then discarded, which is time-consuming. In contrast, the singleton only performs one allocation.
Implementation (in C++)
Basic implementation (without parameters)
//// Declarationclass Element;class ElementA;class ElementB;class SingleServingVisitor;... // Same as with the
visitor pattern .// Definitionclass SingleServingVisitor {protected: SingleServingVisitor();public: ~SingleServingVisitor();
static void applyTo(Element*); virtual void visitElementA(ElementA*) = 0; virtual void visitElementB(ElementB*) = 0;}
// Implementationvoid SingleServingVisitor::applyTo(Element* elem){ SingleServingVisitor* ssv = new SingleServingVisitor(); elem->accept(ssv); delete ssv;}
Passing parameters
If the single-serving visitor has to be initialised, the parameters have to be passed through the static method:
void SingleServingVisitor::applyTo(Element* elem, TYPE param1, TYPE param2, ...){ SingleServingVisitor ssv(param1, param2, ...); elem->accept(&ssv);}Implementation as a singleton
This implementation ensures:
* that there is at most one instance of the single-serving visitor
* that the visitor can be accessed later// Definitionclass SingleServingVisitor {protected: static SingleServingVisitor* _instance; TYPE _param1; TYPE _param2;SingleServingVisitor();
static SingleServingVisitor* getInstance(); // Note: getInstance method does not need to be public
public: ~SingleServingVisitor();
static void applyTo(Element*);
// static methods to access parameters static void setParam1(TYPE); static void setParam2(TYPE);
virtual void visitElementA(ElementA*) = 0; virtual void visitElementB(ElementB*) = 0;}
// ImplementationSingleServingVisitor* SingleServingVisitor::_instance = NULL;
SingleServingVisitor* SingleServingVisitor::getInstance() { if (_instance = NULL) _instance = new SingleServingVisitor(); return _instance;}
void SingleServingVisitor::applyTo(Element* elem){ elem->accept( getInstance() );}
void SingleServingVisitor::setParam1(TYPE param1){ getInstance()->_param1 = param1;}
void SingleServingVisitor::setParam2(TYPE param2){ getInstance()->_param2 = param2;}
Related patterns
*
Visitor pattern , from which this pattern derives
*Composite pattern : single-serving visitor is often applied to hierarchies of elements
*Singleton pattern
Wikimedia Foundation. 2010.