← Back to home

Visitor

By Pscodium · 8/4/2026 · 3 views

Visitor

O Visitor permite adicionar novas operações a uma estrutura de objetos sem modificar as classes desses objetos.

Ele é especialmente útil quando temos uma estrutura de objetos estável, mas precisamos adicionar constantemente novas operações sobre ela.

Imagine uma árvore de elementos:

Document
├── Text
├── Image
└── Video

Podemos querer realizar operações como:

Exportar para HTML
Exportar para PDF
Calcular tamanho
Validar
Gerar estatísticas

Sem Visitor, poderíamos adicionar vários métodos diretamente nas classes.

Com Visitor, cada operação fica separada.


Elementos

Criamos:

interface Element {
  accept(
    visitor: Visitor
  ): void;
}

Texto:

class TextElement
  implements Element {

  constructor(
    public content: string
  ) {}

  accept(
    visitor: Visitor
  ) {
    visitor.visitText(this);
  }
}

Imagem:

class ImageElement
  implements Element {

  constructor(
    public url: string
  ) {}

  accept(
    visitor: Visitor
  ) {
    visitor.visitImage(this);
  }
}

Visitor

Criamos:

interface Visitor {
  visitText(
    element: TextElement
  ): void;

  visitImage(
    element: ImageElement
  ): void;
}

Agora podemos criar um Visitor para exportar HTML:

class HtmlVisitor
  implements Visitor {

  visitText(
    element: TextElement
  ) {
    console.log(
      `<p>${element.content}</p>`
    );
  }

  visitImage(
    element: ImageElement
  ) {
    console.log(
      `<img src="${element.url}" />`
    );
  }
}

Uso:

const elements: Element[] = [
  new TextElement(
    "Olá mundo"
  ),

  new ImageElement(
    "image.png"
  )
];

Executamos:

const visitor =
  new HtmlVisitor();

for (
  const element
  of elements
) {
  element.accept(visitor);
}

Resultado:

<p>Olá mundo</p>
<img src="image.png" />

Adicionando uma nova operação

Agora queremos gerar Markdown.

Não precisamos alterar:

TextElement
ImageElement

Criamos outro Visitor:

class MarkdownVisitor
  implements Visitor {

  visitText(
    element: TextElement
  ) {
    console.log(
      element.content
    );
  }

  visitImage(
    element: ImageElement
  ) {
    console.log(
      `![Imagem](${element.url})`
    );
  }
}

Agora podemos usar:

const markdown =
  new MarkdownVisitor();

for (
  const element
  of elements
) {
  element.accept(markdown);
}

A mesma estrutura pode ser processada de diferentes maneiras.


Quando usar?

Visitor é útil quando:

  • Temos uma estrutura de objetos relativamente estável.
  • Precisamos adicionar muitas operações diferentes.
  • Queremos separar operações das classes de dados.
  • Adicionar novos comportamentos é mais comum do que adicionar novos tipos de objetos.

Exemplos:

ASTs
Compiladores
Interpretadores
Documentos
Sistemas de arquivos
Estruturas de dados complexas

Uma desvantagem é que adicionar um novo tipo de elemento pode exigir alterações em todos os Visitors.

A ideia principal é:

Separar operações da estrutura de objetos sobre a qual essas operações são executadas.



Comments

No comments yet.