O que mais preocupou os próprios autores de Design Patterns foi o padrão "Visitante".
É um "mal necessário" - mas é freqüentemente usado demais e a necessidade dele geralmente revela uma falha mais fundamental em seu projeto.
Um nome alternativo para o padrão "Visitante" é "Multi-dispatch", porque o padrão Visitante é o que você acaba com quando deseja usar uma linguagem OO de despacho de tipo único para selecionar o código a ser usado com base no tipo de dois (ou mais) objetos diferentes.
O exemplo clássico é que você tem a interseção entre duas formas, mas há um caso ainda mais simples que costuma ser esquecido: comparar a igualdade de dois objetos heterogêneos.
De qualquer forma, muitas vezes você acaba com algo assim:
interface IShape
{
double intersectWith(Triangle t);
double intersectWith(Rectangle r);
double intersectWith(Circle c);
}
O problema com isso é que você juntou todas as suas implementações de "IShape". Você deu a entender que sempre que desejar adicionar uma nova forma à hierarquia, você também precisará alterar todas as outras implementações de "Forma".
Às vezes, este é o design mínimo correto - mas pense bem. Seu projeto realmente exige que você despache em dois tipos? Você está disposto a escrever cada uma das explosões combinatórias de métodos múltiplos?
Freqüentemente, ao introduzir outro conceito, você pode reduzir o número de combinações que realmente terá que escrever:
interface IShape
{
Area getArea();
}
class Area
{
public double intersectWith(Area otherArea);
...
}
Claro, depende - às vezes você realmente precisa escrever código para lidar com todos esses casos diferentes - mas vale a pena fazer uma pausa e pensar antes de mergulhar e usar o Visitor. Isso pode lhe poupar muita dor mais tarde.