Visitor Method Design Pattern: A Beginner’s Guide
May 12, 2026 5 Min Read 30 Views
(Last Updated)
Imagine a tax inspector who visits different types of properties: houses, shops, and factories. Each property type is taxed differently. The inspector does not change the properties. The properties do not change either. The inspector simply visits each one and applies the right calculation based on what it is.
That is the Visitor Method Design Pattern in a nutshell. You have a collection of objects. You want to perform an operation on each one. But the operation differs depending on the type of object. Instead of stuffing that logic inside each object, you pull it out into a separate Visitor class that travels through the collection and handles each type.
Quick Answer
The Visitor Method Design Pattern lets you add new operations to a group of objects without changing the objects themselves. You create a Visitor class that knows how to handle each type of object. Each object accepts the visitor and lets it do its work. The objects stay clean. All new logic lives in the visitor.
Table of contents
- What is the Visitor Method Design Pattern?
- How the Visitor Method Design Pattern Works: Step by Step
- Step 1: Create the Visitor Interface
- Step 2: Create the Element Interface
- Step 3: Create the Concrete Elements
- Step 4: Create a Concrete Visitor
- Step 5: Put It All Together
- Adding a New Operation Without Touching the Elements
- A Real Example: Shopping Cart
- When to Use the Visitor Method Design Pattern
- When NOT to Use the Visitor Method Design Pattern
- Quick Reference: The 4 Parts
- Tips for Using the Visitor Method Design Pattern
- 💡 Did You Know?
- Conclusion
- FAQs
- What is double dispatch in the Visitor Method Design Pattern?
- What is the difference between Visitor and Strategy patterns?
- Can I use the Visitor Method Design Pattern in JavaScript?
- Is the Visitor pattern difficult to implement?
- What happens when I add a new element type?
What is the Visitor Method Design Pattern?
The Visitor Method Design Pattern is a behavioral design pattern. Behavioral patterns are about how objects communicate and share responsibility.
Here is the core problem it solves. You have several classes. You want to add a new operation across all of them. The traditional way is to add a new method to every class. That means touching every class every time a new operation is needed. If you have five classes and three new operations, that is fifteen changes spread across your codebase.
The Visitor Method Design Pattern solves this by doing one thing differently: instead of adding the operation to each class, you create one new Visitor class that contains all the logic for that operation.
The four parts of the Visitor Method Design Pattern:
- Visitor: The class that contains the operation logic. Has one method per object type it can visit.
- Concrete Visitor: A specific implementation of the visitor (tax calculator, export tool, report generator)
- Element: The interface that all visitable objects implement. Has one method: accept(visitor)
- Concrete Element: The actual objects being visited (House, Shop, Factory)
Do check out the HCL GUVI AI Software Development Course if you want to master advanced software engineering concepts like the Visitor Method Design Pattern with real-world coding practice. This industry-focused program covers design patterns, system design, backend development, AI-powered applications, and scalable software architecture through hands-on projects, live mentoring, and certifications from IITM Pravartak and MongoDB, helping you become job-ready for modern developer roles.
How the Visitor Method Design Pattern Works: Step by Step
Step 1: Create the Visitor Interface
The Visitor interface declares one visit() method for each type of element it can visit.
Python code
class Visitor:
def visit_house(self, house):
pass
def visit_shop(self, shop):
pass
def visit_factory(self, factory):
pass
One method per element type. Each method receives the element it is visiting.
Step 2: Create the Element Interface
Every object that can be visited must implement accept(). This method receives a visitor and calls the right visit method on it.
Python code
class Element:
def accept(self, visitor: Visitor):
pass
This is the key step. The element calls the visitor. This is called double dispatch, which means the right method is chosen based on both the visitor type and the element type.
Step 3: Create the Concrete Elements
These are the actual objects being visited. Each one calls the correct visit() method on the visitor.
Python code
class House(Element):
def __init__(self, area):
self.area = area
def accept(self, visitor):
visitor.visit_house(self) # tells visitor: I am a House
class Shop(Element):
def __init__(self, revenue):
self.revenue = revenue
def accept(self, visitor):
visitor.visit_shop(self) # tells visitor: I am a Shop
class Factory(Element):
def __init__(self, workers):
self.workers = workers
def accept(self, visitor):
visitor.visit_factory(self) # tells visitor: I am a Factory
Each element knows only one thing: which visit method to call on the visitor. It does not know what the visitor does.
Step 4: Create a Concrete Visitor
Now write the actual operation. All the logic lives here, separated by element type.
Python code
class TaxCalculator(Visitor):
def visit_house(self, house):
tax = house.area * 10
print(f"House tax: Rs. {tax}")
def visit_shop(self, shop):
tax = shop.revenue * 0.15
print(f"Shop tax: Rs. {tax}")
def visit_factory(self, factory):
tax = factory.workers * 500
print(f"Factory tax: Rs. {tax}")
All tax logic is in one class. The House, Shop, and Factory classes are untouched.
Step 5: Put It All Together
Python code
# Create elements
properties = [
House(area=120),
Shop(revenue=50000),
Factory(workers=30)
]
# Create visitor
tax_inspector = TaxCalculator()
# Visit each element
for property in properties:
property.accept(tax_inspector)
Output:
House tax: Rs. 1200
Shop tax: Rs. 7500.0
Factory tax: Rs. 15000
The visitor travels through each property and applies the right tax calculation. None of the property classes were changed.
Adding a New Operation Without Touching the Elements
This is where the Visitor Method Design Pattern pays off. Add a completely new operation by creating one new Visitor class. Zero changes to House, Shop, or Factory.
Python code
class PropertyReport(Visitor):
def visit_house(self, house):
print(f"House report: {house.area} sqm residential property")
def visit_shop(self, shop):
print(f"Shop report: Revenue of Rs. {shop.revenue}")
def visit_factory(self, factory):
print(f"Factory report: Employs {factory.workers} workers")
# Same elements, new visitor
reporter = PropertyReport()
for property in properties:
property.accept(reporter)
Output:
House report: 120 sqm residential property
Shop report: Revenue of Rs. 50000
Factory report: Employs 30 workers
New operation. One new class. Nothing else changed. This is the core value of the Visitor Method Design Pattern.
Riddle: You have a shopping cart with three item types: Book, Electronics, and Clothing. You need to calculate the total price, apply discounts, and generate an invoice. Without the Visitor Method Design Pattern, how many methods do you add across all classes? With it, how many classes do you add?
Answer: Without the visitor: 3 methods × 3 classes = 9 changes across your codebase. With the Visitor Method Design Pattern: 3 new Visitor classes, zero changes to Book, Electronics, or Clothing. Every future operation is also one new class. The objects stay stable.
A Real Example: Shopping Cart
Here is a practical version using items in a shopping cart.
Python code
# Elements
class Book:
def __init__(self, price):
self.price = price
def accept(self, visitor):
visitor.visit_book(self)
class Electronics:
def __init__(self, price):
self.price = price
def accept(self, visitor):
visitor.visit_electronics(self)
class Clothing:
def __init__(self, price):
self.price = price
def accept(self, visitor):
visitor.visit_clothing(self)
# Visitor: calculates discounted price
class DiscountVisitor:
def visit_book(self, book):
print(f"Book: Rs. {book.price * 0.9:.0f} (10% off)")
def visit_electronics(self, item):
print(f"Electronics: Rs. {item.price * 0.85:.0f} (15% off)")
def visit_clothing(self, item):
print(f"Clothing: Rs. {item.price * 0.8:.0f} (20% off)")
# Usage
cart = [Book(500), Electronics(20000), Clothing(1200)]
discount = DiscountVisitor()
for item in cart:
item.accept(discount)
Output:
Book: Rs. 450 (10% off)
Electronics: Rs. 17000 (15% off)
Clothing: Rs. 960 (20% off)
Each item type gets its own discount rule. Adding a new item type (like FoodItem) means adding one new visit_food() method to existing visitors. Adding a new operation (like tax calculation) means creating one new Visitor class.
When to Use the Visitor Method Design Pattern
- When you need to add operations to a stable set of classes without modifying them
- When an operation spans many unrelated classes and you do not want to scatter that logic across all of them
- When you have many distinct operations on the same group of objects (tax, audit, export, report, print)
- Compilers and interpreters: Each node in an abstract syntax tree (AST) accepts visitors for type checking, code generation, and optimisation
- Document export systems: A document tree accepts an HTML visitor, a PDF visitor, or a Markdown visitor without the nodes knowing the format
When NOT to Use the Visitor Method Design Pattern
- When your element classes change frequently: Every time you add a new element type, you must update every existing Visitor class to add the new visit method. If the object structure is unstable, the pattern creates more work than it saves.
- When there is only one operation: If you only ever need to do one thing to your objects, the Visitor Method Design Pattern is overkill.
- When objects are simple: A small flat list of similar objects does not need the visitor structure.
Quick Reference: The 4 Parts
| Part | Role | In the Tax Example |
| Visitor interface | Declares one visit method per element type | Visitor with visit_house, visit_shop, visit_factory |
| Concrete Visitor | Implements the actual operation | TaxCalculator, PropertyReport |
| Element interface | Declares the accept(visitor) method | Element base class |
| Concrete Element | Calls the right visit method on the visitor | House, Shop, Factory |
Tips for Using the Visitor Method Design Pattern
- Use it when your objects are stable but operations keep growing: If new classes get added often, consider a different approach. The Visitor Method Design Pattern works best when the element types are fixed.
- Name your visitors clearly: TaxCalculator, InvoiceGenerator, XMLExporter are clear. Visitor1 is not. Clear names make your visitor list self-documenting.
- Keep each visitor focused on one operation: One visitor should do one thing. Do not combine tax calculation and report generation in the same visitor class.
- Accept can be one line: The accept() method in every element is always one line: call the right visit method on the visitor and pass self. Keep it exactly that simple.
💡 Did You Know?
- Compilers use the Visitor Method Design Pattern heavily. When a compiler processes your code, it builds a tree of nodes (AST). Visitors then travel through that tree to perform type checking, dead code elimination, and code generation without the tree nodes knowing any of those details.
- The Visitor Method Design Pattern is sometimes called the “open-closed principle in action” because it lets you add new operations (open for extension) without modifying existing classes (closed for modification).
Conclusion
The Visitor Method Design Pattern gives you a clean way to add new operations to a group of objects without touching those objects. The objects stay focused on what they are. All new behaviour lives in separate Visitor classes that you can add, remove, or swap freely.
The pattern has four parts: the Visitor interface, the Concrete Visitors that implement operations, the Elements that accept visitors, and the Client that connects them. Once you understand those four parts, the Visitor Method Design Pattern becomes one of the clearest ways to extend a system without breaking what already works.
Start with the tax inspector example. Then try adding your own visitor to the shopping cart. The pattern becomes natural very quickly.
FAQs
1. What is double dispatch in the Visitor Method Design Pattern?
Double dispatch means the right method is chosen based on two types: the visitor type and the element type. When an element calls visitor.visit_house(self), the language picks the method based on both the visitor class and the fact that self is a House. This is how the Visitor Method Design Pattern routes each element to the correct logic automatically.
2. What is the difference between Visitor and Strategy patterns?
Strategy swaps one algorithm for another on the same object. Visitor applies different logic to different object types in a collection. Strategy is about choosing how one thing is done. Visitor is about applying the right operation to each type in a group.
3. Can I use the Visitor Method Design Pattern in JavaScript?
Yes. Create a Visitor object with one method per element type. Each element class has an accept(visitor) method that calls the right visitor method and passes itself. The pattern works the same in JavaScript, TypeScript, Java, and C#.
4. Is the Visitor pattern difficult to implement?
No. The hardest part to understand is the accept() method. Once you see that it just calls visitor.visit_this_type(self), everything else follows naturally. The tax calculator and shopping cart examples in this guide are under 30 lines each.
5. What happens when I add a new element type?
Every existing Visitor class must add a new visit method for the new type. This is the main trade-off of the Visitor Method Design Pattern. It is easy to add new operations but harder to add new element types. This is why the pattern works best when your element types are stable.



Did you enjoy this article?