Before applying Visitor, adding a new operation requires modifying each element class, violating open/closed principle. After applying Visitor, new operations are added as new visitor classes without changing element classes, improving extensibility and separation of concerns.
### Before (without Visitor pattern):
class ElementA:
def operation1(self):
print("ElementA operation1")
def operation2(self):
print("ElementA operation2")
class ElementB:
def operation1(self):
print("ElementB operation1")
def operation2(self):
print("ElementB operation2")
# Adding new operation requires modifying ElementA and ElementB
### After (with Visitor pattern):
class ElementA:
def accept(self, visitor):
visitor.visit_element_a(self)
class ElementB:
def accept(self, visitor):
visitor.visit_element_b(self)
class Visitor:
def visit_element_a(self, element):
pass
def visit_element_b(self, element):
pass
class Operation1Visitor(Visitor):
def visit_element_a(self, element):
print("ElementA operation1")
def visit_element_b(self, element):
print("ElementB operation1")
class Operation2Visitor(Visitor):
def visit_element_a(self, element):
print("ElementA operation2")
def visit_element_b(self, element):
print("ElementB operation2")
# Usage
elements = [ElementA(), ElementB()]
op1 = Operation1Visitor()
for e in elements:
e.accept(op1)
op2 = Operation2Visitor()
for e in elements:
e.accept(op2)