Одноразовий відвідувач () — шаблон поведінки. Призначений для оптимізації роботи шаблону відвідувач (Visitor). Використовується лише один раз, після закінчення всіх операцій він видаляється(у більшості випадків).

Використання

Цей шаблон поведінки є особливим випадком використання паттерна «відвідувач», тому його потрібно застосовувати у певних особливих випадках, таких як:

В програмі має бути тільки один екземпляр такого відвідувача. В певних випадках можна реалізувати такого відвідувача, як одинака. При цьому можна бути впевненим, що відвідувач може бути викликаний пізніше без змін параметрів. Він є особливим випадком реалізації паттерна «відвідувач», тож він також описує операцію, яка виконується над об'єктами інших класів, він може виконати ті ж самі функції, що і у випадку звичайного паттерну «відвідувач», але після виконання ним заданих функцій він видаляється. Після виконання певної операції програми, не потрібно щоб відвідувачі залишитися в пам'яті. Це часто трапляється при відвідуванні великої кількості об'єктів, або ієрархії (наприклад, коли шаблон відвідувач використовується разом з шаблоном Компоновщик) для виконання одного завдання на ньому. Шаблон регулярного відвідувача слід використовувати, коли відвідувач повинен залишитися в пам'яті. Це потрібно для того щоб встановити відвідувачем ряд налаштувань, які будуть збережені в пам'яті для пізнього використання відвідувачем.

Приклади використання

Паттерн одноразового відвідувача викликається через проміжні шари статичних методів

Реалізація на C++

Без параметрів: Element* elem; SingleServingVisitor::apply_to(elem); З параметрами: Element* elem; TYPE param1, param2; SingleServingVisitor::apply_to(elem, param1, param2);

Реалізація на C#

Без параметрів: public static Element elem; SingleServingVisitor.apply_to(elem); З параметрами: public static Element elem; public static TYPE param1 = new TYPE(); public static TYPE param2 = new TYPE(); SingleServingVisitor.apply_to(elem, param1, param2); Наслідки

Переваги - Відвідувачі викликаються при необхідності і можуть знищуватися без будь-якої шкоди. Тим самим не створюючи "зомбованих об'єктів"

- Відвідувач створюється, використовується і знищується від єдиного виклику певного статичного методу який був для цього призначений. Недоліки - Є істотний недолік у тому, що одноразовий відвідувач при виклику певного методу, він спочатку створюється, а потім знищується, це непродуктивна операція, яка забирає достатньо велику кількість часу.

Передавання параметрів

Якщо одноразовий відвідувач був ініціалізований, то параметри повинні передаватися через статичний метод:

Реалізація на C++

void SingleServingVisitor::apply_to(Element* elem, TYPE param1, TYPE param2, ...) { SingleServingVisitor ssv(param1, param2, ...); elem.accept(&ssv); }

Реалізація на C# public partial class SingleServingVisitor { public void apply_to(Element elem, TYPE param1, TYPE param2, ... ) { SingleServingVisitor ssv = new SingleServingVisitor(param1, param2, ...); elem.accept(ssv);

Використання як одинака (singleton) Така реалізація забезпечує:

- Не більше одного екземпляра самообслуговуючого відвідувача

- Доступ до відвідувача може бути надано пізніше

Реалізація на C++

// Призначення class SingleServingVisitor { protected: static SingleServingVisitor* instance_; TYPE param1_; TYPE param2_; SingleServingVisitor(); static SingleServingVisitor* get_instance(); // Зауваження: метод get_instance не повинен бути публічним public: ~SingleServingVisitor(); static void apply_to(Element*); //статичні методи для доступу до параметрів static void set_param1(TYPE); static void set_param2(TYPE);

virtual void visit_ElementA(ElementA*) = 0; virtual void visit_ElementB(ElementB*) = 0; } // Реалізація 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; }

Реалізація на C# // Призначення public abstract class SingleServingVisitor { protected static SingleServingVisitor instance_ = null; protected TYPE param1_ = new TYPE(); protected TYPE param2_ = new TYPE(); // Реалізація

protected static SingleServingVisitor get_instance() { if (this.instance_ == null) this.instance_ = new SingleServingVisitor(); return this.instance_;

// Зауваження: метод get_instance не повинен бути публічним SingleServingVisitor(); public static void apply_to(Element elem) { elem.accept(get_instance());

//статичні методи для доступу до параметрів public static void set_param1(TYPE param1) { getInstance().param1_ = param1;

public static void set_param2(TYPE param2) { getInstance().param2_ = param2;

public abstract void visit_ElementA(ElementA NamelessParameter);

public abstract void visit_ElementB(ElementB NamelessParameter); }