Egyszer használatos látogató programtervezési minta
Az egyszer használatos látogató programtervezési minta a számítógép-programozás egyik tervmintája. Célja a látogató programtervezési minta optimalizálása: a látogatót allokálja, felhasználja, majd deallokálja.
Alkalmazhatósága
[szerkesztés]A minta akkor alkalmazható, ha nincs szükség arra, hogy a látogató megmaradjon a memóriában. Gyakran ez az eset, ha egyszer kell egy műveletet végrehajtani egy hierarchia objektumain (lásd összetétel programtervezési minta), például megszámolni a kamerákat.
Vannak esetek, amikor a látogatónak sokáig meg kell maradnia a memóriában. Ez általában akkor fordul elő, ha parametrizálva van, és az adatokhoz később is hozzá kell férni. Például az összegyűjtött renderelési opciókat tárolja.
Ha a látogatóból csak egy példány kell, akkor van értelme annak, hogy egyke legyen, és az egyszer használatos látogatóhoz hasonlóan legyen megvalósítva. Ekkor az egyszer használatos látogató később is meghívható ugyanazokkal a paraméterekkel.
Használati példák
[szerkesztés]Az egyszer használatos látogató osztálymetódusok közvetítésével hívható
Paraméter nélkül:
Element* elem;
SingleServingVisitor::apply_to(elem);
Paraméteresen:
Element* elem;
TYPE param1, param2;
SingleServingVisitor::apply_to(elem, param1, param2);
Egykeként:
Element* elem;
TYPE param1, param2;
SingleServingVisitor::set_param1(param1);
SingleServingVisitor::set_param2(param2);
SingleServingVisitor::apply_to(elem);
Előnyök és hátrányok
[szerkesztés]- Nincsenek zombi objektumok, amik feleslegesen foglalnák a memóriát. Amikor szükség van a látogatóra, az létrejön, elvégzi a feladatát, utána törlődik.
- Egyszerűbb interfész, mint a látogatónál. Mindezek a műveletek egyetlen osztálymetódusban mennek végbe.
- Ismételt allokáció. Ha többször hívják az apply_to metódust, akkor a látogató mindannyiszor létrejön és törlődik.
Megvalósítások
[szerkesztés]Az alábbi megvalósítások C++-ban íródtak:
Paraméterek nélkül
[szerkesztés]// Declaration
class Element;
class ElementA;
class ElementB;
class SingleServingVisitor;
... // Same as with the [[visitor pattern]].
// Definition
class SingleServingVisitor {
protected:
SingleServingVisitor();
public:
~SingleServingVisitor();
static void apply_to(Element*);
virtual void visit_ElementA(ElementA*) = 0;
virtual void visit_ElementB(ElementB*) = 0;
}
// Implementation
void SingleServingVisitor::apply_to(Element* elem)
{
SingleServingVisitor ssv;
elem.accept(ssv);
}
Paraméteres
[szerkesztés]Ha a látogató konstrukciójához paraméterek kellenek, azokat az osztálymetódus veszi át:
void SingleServingVisitor::apply_to(Element* elem, TYPE param1, TYPE param2, ...)
{
SingleServingVisitor ssv(param1, param2, ...);
elem.accept(&ssv);
}
Egykeként
[szerkesztés]Az alábbi megvalósítás biztosítja, hogy egy példány legyen, és a látogató később is hozzáférhető legyen:
// Definition
class SingleServingVisitor {
protected:
static SingleServingVisitor* instance_;
TYPE param1_;
TYPE param2_;
SingleServingVisitor();
static SingleServingVisitor* get_instance();
// Note: get_instance method does not need to be public
public:
~SingleServingVisitor();
static void apply_to(Element*);
// static methods to access parameters
static void set_param1(TYPE);
static void set_param2(TYPE);
virtual void visit_ElementA(ElementA*) = 0;
virtual void visit_ElementB(ElementB*) = 0;
}
// Implementation
SingleServingVisitor* SingleServingVisitor::instance_ = NULL;
SingleServingVisitor* SingleServingVisitor::get_instance()
{
if (this->instance_ == NULL)
this->instance_ = new SingleServingVisitor();
return this->instance_;
}
void SingleServingVisitor::apply_to(Element* elem)
{
elem->accept(get_instance());
}
void SingleServingVisitor::set_param1(TYPE param1)
{
getInstance()->param1_ = param1;
}
void SingleServingVisitor::set_param2(TYPE param2)
{
getInstance()->param2_ = param2;
}
Fordítás
[szerkesztés]Ez a szócikk részben vagy egészben a Single-serving visitor pattern című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.