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 the composite 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)

 //// Declaration class Element; class ElementA; class ElementB; class SingleServingVisitor;  ... // Same as with the visitor pattern.  // Definition class SingleServingVisitor { protected: 
   SingleServingVisitor(); 
public:
   ~SingleServingVisitor(); 
   static void applyTo(Element*);   virtual void visitElementA(ElementA*) = 0;   virtual void visitElementB(ElementB*) = 0; 
} // Implementation void 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 = new SingleServingVisitor(param1, param2, ...);   elem->accept(ssv);   delete 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
 // Definition class 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; 
} // Implementation SingleServingVisitor* 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

 

<< PreviousWord BrowserNext >>
amphitere
g1
thorkil vanggaard
x 302
g0
s. w. burnham
the proclaimers
x 303
frank brunner
rookery
distributed transaction
minh thai
the book of concord
pan sonic
g0 phase
bruce hornsby
juvenile arthritis
thomas rhymer
the aristocrats
qubcois libre
first comics
cressy class cruiser
qumnven
paris district high school
tara hitchcock
joel hastings metcalf
sagamore hill
trophy
hms bacchante (1901)
mark saville, baron saville of newdigate
paris fall fair
origin of replication
este lauder (person)
edwin foster coddington
detroit (disambiguation)
hms bacchante
veil of perception
paris skatepark
pre replication complex
robert p. casey
bruce perens' open source series
walter mccrone
cyclin
river nith