6.10. Visitor¶
EN: Visitor
PL: Odwiedzający
Type: object
6.10.1. Pattern¶
Add new operations to an object structure without modifying it
For building editors
Open/Close Principle

6.10.2. Problem¶

6.10.3. Solution¶

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
class HtmlNode(ABC):
@abstractmethod
def execute(self, operation: 'Operation') -> None:
pass
class HeadingNode(HtmlNode):
def execute(self, operation: 'Operation') -> None:
operation.apply_heading(self)
class AnchorNode(HtmlNode):
def execute(self, operation: 'Operation') -> None:
operation.apply_anchor(self)
class Operation(ABC):
"""Visitor"""
@abstractmethod
def apply_heading(self, heading: HeadingNode) -> None:
pass
@abstractmethod
def apply_anchor(self, anchor: AnchorNode) -> None:
pass
class HighlightOperation(Operation):
def apply_heading(self, heading: HeadingNode) -> None:
print('highlight-heading')
def apply_anchor(self, anchor: AnchorNode) -> None:
print('apply-anchor')
class PlaintextOperation(Operation):
def apply_heading(self, heading: HeadingNode) -> None:
print('text-heading')
def apply_anchor(self, anchor: AnchorNode) -> None:
print('text-anchor')
@dataclass
class HtmlDocument:
nodes: list[HtmlNode] = field(default_factory=list)
def add(self, node: HtmlNode) -> None:
self.nodes.append(node)
def execute(self, operation: Operation) -> None:
for node in self.nodes:
node.execute(operation)
if __name__ == '__main__':
document = HtmlDocument()
document.add(HeadingNode())
document.add(AnchorNode())
document.execute(PlaintextOperation())
# class Operation:
# @abstractmethod
# @singledispatchmethod
# def apply(arg):
# raise NotImplementedError('Argument must be HtmlNode')
#
# @abstractmethod
# @apply.register
# def _(self, heading: HeadingNode):
# pass
#
# @abstractmethod
# @apply.register
# def _(self, anchor: AnchorNode):
# pass