Padrões de Projeto Padrões de Criação Abstract Factory Prof. Eduardo N F Zagari Prof. Ivan Granja Abstract Factory Provê uma interface para criação de famílias de objetos relacionados ou dependentes sem especificar suas classes concretas Mesmo conceito de Method Factory, porém um nível de abstração acima Pode ser implementado, em Java, tanto como interface como com classe abstrata Também conhecido como Kit 2 1
Motivação 3 Motivação Considere uma interface de usuário que suporte múltiplos look-and-feel. Para ser portável, uma aplicação não deveria se referir aos elementos (widgets) de um padrão particular de forma hard-code Solução: WidgetFactory uma interface para criar cada tipo básico de elementos Uma classe abstrata para cada tipo de widget Uma subclasse concreta para cada padrão distinto Clientes usam a WidgetFactory e não têm conhecimento das classes que implementam widgets particulares WidgetFactory assegura também consistência entre classes 4 2
Aplicação Use Abstract Factory quando: O sistema deve ser independente de como seus produtos são criados, compostos e representados O sistema deve ser configurado com uma ou com múltiplas famílias de produtos Uma família de objetos de produtos relacionados é projetada para ser usada de forma conjunta e você deva garantir esta restrição Você quer prover uma biblioteca de classes de produtos e quer revelar apenas suas interfaces e não suas implementações 5 Aplicação Deseja-se criar instâncias de um conjunto de classes relacionadas, sem que se saiba qual classe factory concreta deve ser instanciada. Na falta de uma classe abstrata, o cliente deve manter um critério de seleção para selecionar qual das interfaces disponíveis deve ser usada, em tempo de execução. Ajuda a evitar duplicação de interfaces para criação das instâncias, eliminado a necessidade da classe cliente ter que conhecer diversas interfaces para as diversas classes concretas. 6 3
Estrutura 7 Participantes AbstractFactory (WidgetFactory) Declara uma interface para operações que criam objetos-produto abstratos ConcreteFactory (MotifWidgetFactory, PMWidgetFactory) Implementa as operações para criar objetos-produto concretos AbstractProduct (Window, ScrollBar) Declara uma interface para um tipo de objeto-produto 8 4
Participantes ConcreteProduct (MotifWindow, MotifScrollBar) Define um objeto-produto a ser criado pela fábrica concreta correspondente Implementa a interface AbstractProduct Cliente Usa somente as interfaces declaradas pelas classes AbstractFactory e AbstractProduct 9 Colaborações AbstractFactory delega a criação de objetos-produto a suas subclasses ConcreteFactory. Normalmente uma única instância da classe ConcreteFactory é criada. Para criar objetos-produto diferentes, os clientes devem usar uma fábrica concreta diferente. 10 5
Conseqüências 1. Isola classes concretas 2. Facilita a permuta de famílias de produtos 3. Promove consistência entre produtos 4. Dificulta o suporte a novos tipos de produtos 11 Exemplo II Car SUV ver Código Java (Workspace) 6
Exemplo III Manutenção de Dados de Clientes Validar e salvar os dados de entrada de um cliente (conta, endereço e cartão) Aplicação deve rodar local e remotamente No modo remoto, deve fazer uso dos objetos remotos por meio de RMI e salvar os dados no servidor central. Permanecer funcionado quando o servidor remoto estiver fora do ar Sincronização entre servidor local e central é parte de outra aplicação específica para isso. Diagrama de Pacotes 7
Visão Interna dos pacotes Visão Interna dos pacotes 8
Visão Interna dos pacotes Visão Interna dos pacotes 9
Visão Interna dos pacotes Visão Geral 10
Diagrama de Seqüência Implementação Fábricas geralmente são melhor implementadas como Singletons AbstractFactory deve apenas declarar uma interface para a criação de produtos. É necessário haver uma fábrica concreta (eventualmente, uma para cada famíla de produtos) Definir fábricas extensíveis a novos tipos de produtos: acrescentar parâmetro às operações que criam objetos 22 11
Exemplo 23 Exemplo 24 Livro Texto: Design Pattern - Elements of Reusable OO Software - Gamma 12
Exemplo Para criar um labirinto com cômodos encantados, basta fazer subclasse de MazeFactory. 25 Exemplo 26 13
Exemplo Para criar um labirinto que contenha cômodos encantados, basta chamar CreateMaze com um EnchantedMazeFactory: MazeGame game; EnchantedMazeFactory factory; game.createmaze(factory); 27 Exemplo Agora, suponha que se queira fazer um labirinto no qual o cômodo pode ter uma bomba e a parede pode ser/estar danificada por ela. Deve-se fazer subclasses novamente, sobrescrevendo os dois métodos... 28 14
Exemplo 29 Exemplo Para criar um labirinto que contenha bombas, basta chamar CreateMaze com um BombedMazeFactory 30 15
Notas Note que MazeFactory é apenas uma coleção de métodos fábrica Note também que ela é tanto uma AbstractFactory como uma ConcreteFactory Se um RoomWithABomb tiver que acessar um membro de um BombedWall, então ele deveria fazer um cast da referência de Wall * para BombedWall * (o que é seguro!!!) 31 16