Um dos propósitos que nos leva a agruparmos objetos numa mesma estrutura é facilitar a execução de operações envolvendo as partes que constituem esse objeto. Ou seja, operações nas quais percorreremos todos os elementos e aplicaremos a cada um deles a operação desejada. Nesse processo, a existência de objetos de tipos distintos deve ser levada em conta porque uma mesma operação pode ter significado diferente, dependente do tipo de objeto. Isto nos leva a ter que escolher a versão correta da operação que deve ser executada em cada elemento. Por exemplo, considere que você tem uma classe representando a lista de recursos necessários para fabricar um produto. A lista inclui as matérias primas, as máquinas envolvidas e até roteiros descrevendo o processo de fabricação. Uma operação que imprima a estrutura terá que considerar as diferenças entre cada uma dessas partes pois elas têm informações específicas distintas.
Em princípio, parece que uma herança simples pode resolver a questão. Mas, e se for necessário acrescentar novos tipos de operação, com nomes e parâmetros diferentes - salvar em formato XML, por exemplo ? Teríamos que alterar a estrutura da agregação para que ela comporte a nova operação.
O intuito do Design Pattern comportamental Visitor é facilitar a manutenção desse tipo de estrutura heterogênea. Ele nos obriga a manter separada a estrutura de um objeto e os algoritmos das operações que podem ser aplicadas sobre seus componentes. Com isso, podemos introduzir novas operações à estrutura sem que seja preciso modificar as classes onde essas operações serão aplicadas. Em outras palavras, o que o Visitor propõe é transferir a implementação das operações, removendo-as das classes que compõem a agregação e passando-as para classes próprias. Com isso, preserva-se a estrutura original tanto da agregação quanto das partes que a compõem.
O diagrama abaixo mostra um exemplo prático da aplicabilidade desse padrão. Nele, um Produto Acabado é composto de uma lista de recursos, incluindo as matérias primas, máquinas e instruções para a fabricação dele. São definidas duas operações externas : uma para exportar a arquitetura do produto para XML e outra para imprimí-la.
De acordo com o papel que exercem na implementação de uma solução para o padrão Visitor, as classes envolvidas são formalmente conhecidas pelos nomes que seguem:






O padrão Iterator também é projetado para permitir a navegação entre elementos que compõem um objeto. A diferença é que no Iterator os elementos devem ser herança de uma mesma classe enquanto no Visitor isso não é obrigatório.
O cenário onde o padrão Visitor é aplicável se assemelha ao uso de interfaces, já que em ambos os casos, uma estrutura externa estabelece as operações que a classe é capaz de executar. No entanto, interfaces forçam a implementação das operações dentro da classe ao invés de fazê-lo em classes separadas, como no Visitor. Obviamente, ambos os recursos podem ser utilizados em conjunto para produzir uma solução mais flexível.
Alguns críticos alegam que o Visitor fere o encapsulamento das classes ao obrigar que parte de seu funcionamento seja delegada a outra classe. Mas, podemos encarar essa classe extra como uma operação distinta, minimizando ou até mesmo eliminando o efeito da quebra de encapsulamento.
No próximo post eu mostro uma sugestão de implementação desse pattern usando o Delphi.