Одноразовий відвідувач (шаблон поведінки)
Одноразовий відвідувач (англ. Single-serving visitor) - шаблон поведінки. Він призначений для того щоб оптимізувати роботу шаблону відвідувач (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);
}