Awesome-claude-code create-visitor

Generates Visitor pattern for PHP 8.4. Creates operations on object structures without modifying element classes, with visitor interface, concrete visitors, and visitable elements. Includes unit tests.

install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/create-visitor" ~/.claude/skills/dykyi-roman-awesome-claude-code-create-visitor && rm -rf "$T"
manifest: skills/create-visitor/SKILL.md
source content

Visitor Pattern Generator

Creates Visitor pattern infrastructure for operations on object structures without modifying classes.

When to Use

ScenarioExample
Operations on object structureCalculate price/tax on order items
Adding operations without modificationExport visitors (JSON, XML, CSV)
Different operations on same elementsValidation, transformation, rendering
Double dispatch neededType-specific behavior without instanceof

Component Characteristics

Visitor Interface

  • Declares visit methods for each element type
  • One method per visitable element
  • Returns operation result
  • Enables double dispatch

Concrete Visitors

  • Implement specific operations
  • Process each element type differently
  • Encapsulate algorithm logic
  • Can accumulate state during traversal

Visitable Elements

  • Accept visitor via accept() method
  • Call visitor's visit method with self
  • Enable operation without modification
  • Maintain element structure

Generation Process

Step 1: Generate Visitor Interface

Path:

src/Domain/{BoundedContext}/Visitor/

  1. {Name}VisitorInterface.php
    — Visitor contract with visit methods

Step 2: Generate Concrete Visitors

Path:

src/Domain/{BoundedContext}/Visitor/
or
src/Application/{BoundedContext}/

  1. {Operation1}Visitor.php
    — First operation implementation
  2. {Operation2}Visitor.php
    — Second operation implementation
  3. {Operation3}Visitor.php
    — Third operation implementation

Step 3: Generate Visitable Interface

Path:

src/Domain/{BoundedContext}/

  1. VisitableInterface.php
    — Element contract with accept() method

Step 4: Update Existing Elements

Path:

src/Domain/{BoundedContext}/

  1. Add
    implements VisitableInterface
    to element classes
  2. Add
    accept()
    method to each element

Step 5: Generate Tests

  1. {Operation}VisitorTest.php
    — Individual visitor tests
  2. {Element}AcceptTest.php
    — Element accept() tests

File Placement

ComponentPath
Visitor Interface
src/Domain/{BoundedContext}/Visitor/
Concrete Visitors (Domain)
src/Domain/{BoundedContext}/Visitor/
Concrete Visitors (Application)
src/Application/{BoundedContext}/Visitor/
Visitable Interface
src/Domain/{BoundedContext}/
Unit Tests
tests/Unit/Domain/{BoundedContext}/Visitor/

Naming Conventions

ComponentPatternExample
Visitor Interface
{Name}VisitorInterface
OrderItemVisitorInterface
Concrete Visitor
{Operation}Visitor
PriceCalculatorVisitor
Visitable Interface
VisitableInterface
VisitableInterface
Visit Method
visit{ElementType}()
visitProduct()
Accept Method
accept()
accept()
Test
{ClassName}Test
PriceCalculatorVisitorTest

Quick Template Reference

Visitor Interface

interface {Name}VisitorInterface
{
    public function visit{Element1}({Element1} $element): {ReturnType};
    public function visit{Element2}({Element2} $element): {ReturnType};
    public function visit{Element3}({Element3} $element): {ReturnType};
}

Concrete Visitor

final class {Operation}Visitor implements {Name}VisitorInterface
{
    public function visit{Element1}({Element1} $element): {ReturnType}
    {
        // Element1-specific operation
    }

    public function visit{Element2}({Element2} $element): {ReturnType}
    {
        // Element2-specific operation
    }
}

Visitable Interface

interface VisitableInterface
{
    public function accept({Name}VisitorInterface $visitor): mixed;
}

Visitable Element

final readonly class {Element} implements VisitableInterface
{
    public function accept({Name}VisitorInterface $visitor): mixed
    {
        return $visitor->visit{Element}($this);
    }
}

Usage Example

// Create elements
$order = new Order(items: [
    new Product(price: 100, quantity: 2),
    new Service(price: 50, duration: 1),
    new Discount(amount: 20),
]);

// Apply different visitors
$priceVisitor = new PriceCalculatorVisitor();
$taxVisitor = new TaxCalculatorVisitor(rate: 0.2);
$exportVisitor = new JsonExportVisitor();

$totalPrice = $order->accept($priceVisitor);
$totalTax = $order->accept($taxVisitor);
$json = $order->accept($exportVisitor);

Common Visitor Operations

DomainVisitors
Order ItemsPriceCalculator, TaxCalculator, DiscountApplier
AST/Expression TreeEvaluator, Formatter, Validator
Document StructureRenderer, Counter, Searcher
File SystemSizeCalculator, Permissions, Backup
Shopping CartTotalCalculator, ShippingCost, Export

Anti-patterns to Avoid

Anti-patternProblemSolution
instanceof in visitorDefeats purposeUse proper visit methods
Mutable visitor stateRace conditionsUse readonly classes
Too many element typesVisitor interface bloatSplit into multiple visitors
Breaking element encapsulationTight couplingExpose getters, not internals
Returning voidLimited usefulnessReturn operation results

References

For complete PHP templates and examples, see:

  • references/templates.md
    — Visitor Interface, Concrete Visitor, Visitable Element templates
  • references/examples.md
    — PriceCalculator, TaxCalculator, Export visitors with tests