Visitor pattern: Difference between revisions
Content added Content deleted
m (julia example) |
(Add Python) |
||
Line 175: | Line 175: | ||
Visiting body. |
Visiting body. |
||
Visiting engine. |
Visiting engine. |
||
Visiting car. |
|||
Kicking my front left wheel. |
|||
Kicking my front right wheel. |
|||
Kicking my back left wheel. |
|||
Kicking my back right wheel. |
|||
Moving my body. |
|||
Starting my engine. |
|||
Starting my car. |
|||
</pre> |
|||
=={{header|Python}}== |
|||
<syntaxhighlight lang="python"> |
|||
"""An example of the visitor pattern using structural pattern matching. |
|||
Requires Python >= 3.10. |
|||
""" |
|||
from __future__ import annotations |
|||
from abc import ABC |
|||
from abc import abstractmethod |
|||
class CarElement(ABC): |
|||
def accept(self, visitor: CarElementVisitor) -> None: |
|||
visitor.visit(self) |
|||
class CarElementVisitor(ABC): |
|||
@abstractmethod |
|||
def visit(self, car_element: CarElement) -> None: |
|||
"""Override this in `CarElementVisitor` subclasses.""" |
|||
class Body(CarElement): |
|||
"""Car body.""" |
|||
class Engine(CarElement): |
|||
"""Car engine.""" |
|||
class Wheel(CarElement): |
|||
"""Car wheel""" |
|||
def __init__(self, name: str) -> None: |
|||
self.name = name |
|||
class Car(CarElement): |
|||
def __init__(self) -> None: |
|||
self.elements: list[CarElement] = [ |
|||
Wheel("front left"), |
|||
Wheel("front right"), |
|||
Wheel("back left"), |
|||
Wheel("back right"), |
|||
Body(), |
|||
Engine(), |
|||
] |
|||
def accept(self, visitor: CarElementVisitor) -> None: |
|||
for element in self.elements: |
|||
visitor.visit(element) |
|||
super().accept(visitor) |
|||
class CarElementDoVisitor(CarElementVisitor): |
|||
def visit(self, car_element: CarElement) -> None: |
|||
match car_element: |
|||
case Body(): |
|||
print("Moving my body.") |
|||
case Car(): |
|||
print("Starting my car.") |
|||
case Wheel() as wheel: |
|||
print(f"Kicking my {wheel.name} wheel.") |
|||
case Engine(): |
|||
print("Starting my engine.") |
|||
class CarElementPrintVisitor(CarElementVisitor): |
|||
def visit(self, car_element: CarElement) -> None: |
|||
match car_element: |
|||
case Body(): |
|||
print("Visiting body.") |
|||
case Car(): |
|||
print("Visiting car.") |
|||
case Wheel() as wheel: |
|||
print(f"Visiting my {wheel.name} wheel.") |
|||
case Engine(): |
|||
print("Visiting my engine.") |
|||
if __name__ == "__main__": |
|||
car = Car() |
|||
car.accept(CarElementPrintVisitor()) |
|||
car.accept(CarElementDoVisitor()) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Visiting my front left wheel. |
|||
Visiting my front right wheel. |
|||
Visiting my back left wheel. |
|||
Visiting my back right wheel. |
|||
Visiting body. |
|||
Visiting my engine. |
|||
Visiting car. |
Visiting car. |
||
Kicking my front left wheel. |
Kicking my front left wheel. |