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.