Skip to main content

What It Is

The Visitor pattern adds a new operation to a family of types without changing them. The types learn one thing once — accept(visitor) — and from then on, every new operation is just a new visitor with one method per type.

It flips the usual trade: adding operations becomes easy, adding types becomes the expensive change.


Example: Operations over Shapes

The shapes never change again. Printing areas is one visitor, naming them is another — and an export-to-SVG visitor tomorrow would touch neither Circle nor Rectangle.

New operations, untouched types

Both visitors walk the same shape list through the same accept door. Each visitor holds the whole operation in one place, instead of scattering it across the types.

Prompt
Write a Python program with the Visitor pattern: Circle and Rectangle dataclass shapes with an accept method, a Visitor protocol with visit_circle and visit_rectangle, an AreaPrinter visitor printing each shape's area and a NamePrinter visitor printing each shape's name. Walk a list of shapes with both visitors.
Output: complete Python program

When to Use It

Use it when a stable family of types keeps growing new operations — compilers visiting syntax trees, documents gaining exporters, shapes gaining renderers and measurers.

Skip it when the type family still grows: every new type forces a change in every visitor. In many Python programs a match statement over the types does the same job with less machinery — reach for the visitor when the operations, not the types, are multiplying.


Pros and Cons

Pros: whole operations live in one class each; new operations need zero changes to the visited types; related logic stops being scattered.

Cons: the double dispatch (accept calling back) confuses newcomers; adding one visited type means editing every visitor; the visited family's interface is frozen early.