Одноразовий відвідувач (шаблон поведінки)

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Одноразовий відвідувач (англ. 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);
}