Назад к вопросам
Middle+
159
questionbank

Что такое паттерн проектирования 'Посетитель' (Visitor)?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Паттерн проектирования 'Посетитель' (Visitor) позволяет добавлять новые операции (посетители) к существующей иерархии объектов (элементов) без изменения их структуры.

# Интерфейс элемента
class Element:
    def accept(self, visitor):
        pass

# Конкретные элементы
class ConcreteElementA(Element):
    def accept(self, visitor):
        visitor.visit_concrete_element_a(self)

    def operation_a(self):
        return "Operation A"

class ConcreteElementB(Element):
    def accept(self, visitor):
        visitor.visit_concrete_element_b(self)

    def operation_b(self):
        return "Operation B"

# Интерфейс посетителя
class Visitor:
    def visit_concrete_element_a(self, element):
        pass

    def visit_concrete_element_b(self, element):
        pass

# Конкретные посетители
class ConcreteVisitor1(Visitor):
    def visit_concrete_element_a(self, element):
        print(f"Visitor 1 visiting {element.__class__.__name__}: {element.operation_a()}")

    def visit_concrete_element_b(self, element):
        print(f"Visitor 1 visiting {element.__class__.__name__}: {element.operation_b()}")

class ConcreteVisitor2(Visitor):
    def visit_concrete_element_a(self, element):
        print(f"Visitor 2 visiting {element.__class__.__name__} differently: {element.operation_a().upper()}")

    def visit_concrete_element_b(self, element):
        print(f"Visitor 2 visiting {element.__class__.__name__} differently: {element.operation_b().upper()}")

# Использование
elements = [ConcreteElementA(), ConcreteElementB()]
visitor1 = ConcreteVisitor1()
visitor2 = ConcreteVisitor2()

for element in elements:
    element.accept(visitor1)

for element in elements:
    element.accept(visitor2)

Преимущества:

  • Легкость добавления новых операций: Новая операция реализуется как новый класс посетителя.
  • Разделение ответственности: Логика операций отделена от структуры объектов, над которыми они выполняются.
  • Открыт для расширения, закрыт для модификации: Можно добавлять новые посетители без изменения классов элементов.

Недостатки:

  • Сложно добавить новые элементы: Добавление нового класса элемента требует модификации всех существующих классов посетителей.
  • Нарушение инкапсуляции: Посетитель часто нуждается в доступе к внутреннему состоянию элементов.

Применимость:

  • Когда имеется сложная структура объектов, и нужно выполнять разнообразные несвязанные операции над ними.
  • Когда часто добавляются новые операции, но структура объектов остается относительно стабильной.
  • Когда нужно избежать загрязнения классов элементов множеством операций.