Design Pattern Visitor Projeto de Sistemas de Software Leandra Mara da Silva Motivação • Motivação para o trabalho – Aprimorar conhecimentos de Projeto de Sistemas de Software, realizando um estudo sobre os Padrões de Projeto apresentados em [GoF]. • Objetivo – Fornecer uma visão geral sobre o padrão Visitor. © LES/PUC-Rio Padrão Visitor (Visitante) Visitor • Classificação – Comportamental de objeto: mostra como objetos podem cooperar para executar uma tarefa • Propósito – Representar uma operação a ser realizada sobre os elementos de uma estrutura de objetos como uma classe – Visitantes permitem definir uma nova operação sem mudar as classes dos elementos sobre os quais opera © LES/PUC-Rio Visitor • Motivação (Um Problema a ser resolvido) – Um compilador representa o código como uma árvore sintática; para cada nó precisa realizar algumas operações • Representação Inicial: operações distribuídas entre as classes Pense: Que problemas tal arquitetura pode trazer? © LES/PUC-Rio Visitor • Motivação (continuação) – Problema da arquitetura apresentada: • Sistema difícil de compreender, manter e mudar • Acrescentar uma nova operação exige alteração (e recompilação) de todas essa classes – Como resolver? • E se cada nova operação pudesse ser acrescentada separadamente? • E se as classes nós fossem independentes das operações criadas? © LES/PUC-Rio Visitor • Motivação (Solução) – As possíveis operações são separadas em classes em uma primeira hierarquia NodeVisitor (Hierarquia de Visitantes) – Cada classe de operação (Visitante) trata os parâmetros (nós) possíveis para aquela operação © LES/PUC-Rio Visitor • Motivação (Solução) – em uma segunda hierarquia define-se os elementos sobre os quais se aplicam as operações (hierarquia Node) - a Hierarquia de Visitados – nós passam a ter uma operação para aceitar o Visitor – Resultado: novas operações podem ser adicionadas separadamente e as demais classes tornam-se independentes das operações © LES/PUC-Rio Visitor • Aplicabilidade (use o padrão quando:) – uma estrutura de objetos contém várias classes de objetos com diferentes interfaces, e se deseja fazer operações nesses objetos que dependam de suas classes concretas – queremos separar as operações dos objetos alvo para não “poluir” o código. Visitor nos permite manter as operações definindo-as em uma única classe – O conjunto de objetos-alvo raramente muda (uma vez que cada novo objeto requer novos métodos em todos os visitors), mas frequentemente deseja-se definir novas operações © LES/PUC-Rio Visitor - Estrutura © LES/PUC-Rio Visitor • Participantes – Visitor (NodeVisitor) • Declara uma operação de visita (Visit) para cada classe concreta (ConcreteElement) na estrutura de objetos – ConcreteVisitor (TypeCheckingVisitor) • Implementa cada operação declarada pelo Visitor – Element (Node) • Define uma operação Accept que aceita um Visitor – ConcreteElement (AssignmentNode, VariableRefNode) • Implementa uma operação Accept que aceita um visitante como argumento que chama a operação de visita apropriada desse Visitor – ObjectStructure (Program) • Pode enumerar seus elementos; • Pode fornecer uma interface para permitir ao visitante visitar seus elementos • Pode ser uma composição (um Composite), ou uma coleção, tal como uma lista ou conjunto © LES/PUC-Rio Visitor - Colaborações • O cliente deve criar um Visitor e visitar todos os elementos com este Visitor • A estrutura de objetos chama Accept(Visitor) para cada elemento e esses chamam a operação (do Visitor) que corresponde à sua classe • o Visitor recebe o elemento sendo visitado para poder acessá-lo, se desejado © LES/PUC-Rio Visitor • Conseqüências – Facilidade para incluir novas operações: basta adicionar um novo Visitor – Organização e coesão: visitante reúne operações relacionadas e separa as não relacionadas. Um comportamento relacionado não é espalhado pelas classes que definem a estrutura de objetos – Difícil adicionar novos objetos (ConcreteElement): necessidade de uma nova operação abstrata em Visitor e uma correspondente implementação em cada classe ConcreteVisitor – Visitação de hierarquias de classes: um Visitor pode visitar objetos que não compartilham uma mesma classe mãe. Isso não seria possível, se um mero iterator fosse usado para varrer a estrutura – Acumulação de estados: um visitor pode acumular estados durante as visitas (caso contrário tal estado ficaria em um objeto adicional) – Quebra de encapsulamento: como a operação está dentro de um Visitor, e fora de um ConcreteElement, o ConcreteElement poderá ter que expor mais interfaces do que seria desejável para que o Visitor possa acessá-lo, Isso pode comprometer a encapsulação. © LES/PUC-Rio Visitor • Exemplo de código (classes envolvidas) – CarElement • Wheel (roda): representa um ConcreteElement • Engine (motor): representa um ConcreteElement • Body (carroceria): representa um ConcreteElement – Visitor • PrintVisitor: representa um ConcreteVisitor • DoVisitor : representa um ConcreteVisitor – Car: representa um ObjectStructure – VisitorDemo : é a main; representa o Client © LES/PUC-Rio Visitor – Exemplo de Código © LES/PUC-Rio Visitor – Exemplo de Código Cliente cria objeto ConcreteVisitor O objeto é percorrido por cada visitante © LES/PUC-Rio Fim!!