Padrões de Projeto Padrões de Criação Factory Method Prof. Eduardo N F Zagari Prof. Ivan Granja Factory Method Também conhecido como Construtor Virtual Em muitas aplicações OO, um objeto cliente precisa decidir em tempo de execução qual a sub-classe de uma hierarquia de classes que lhe provê o(s) serviços(s) desejado(s) deve ser acionada. Factory pattern provê mecanismo para tornar esta escolha mais elegante e a seleção torna-se abstrata para a classe cliente. 1
Factory Method Outra: define uma interface para criar um objeto, mas deixa as subclasses decidirem qual classe instanciar. Factory Method faz uma classe delegar a instanciação a subclasses 3 Motivação 1: Seleção de Subclasses sem o pattern factory A escolha pode depender de vários fatores: Estado da Aplicação Parâmetros de configuração da aplicação Evolução ou melhoria nos requisitos Implica que o objeto cliente deve manter uma lógica (muitas vezes complexa) que implementa o algoritmo com o critério de seleção. Essa solução pode levar a diversos problemas: A implementação do critério no objeto cliente implica em alto grau de acoplamento Manutenabilidade é prejudicada, pois o critério pode mudar em função das alterações nos requisitos do software. Requer que o objeto cliente tenha pleno conhecimento das 4 funcionalidades oferecidas pelas classes candidatas da hierarquia que provê o serviço. 2
Modelo UML sem uso do Pattern factory method Cliente é que deve decidir qual subclasse instanciar... Motivação 2 Considere um framework para aplicações que possam apresentar múltiplos documentos ao usuário. Duas abstrações-chave: classes Application e Document (ambas abstratas). Clientes devem especializá-las para executar sua funcionalidade específica. P.ex.: DrawingApplication e DrawingDocument Problema: como a subclasse de Document é específica da aplicação, Application não consegue prever a subclasse que deve instanciar... (sabe apenas QUANDO e não QUAL Document criar) 6 3
Motivação 2 Dilema: o framework deve instanciar classes, mas ele somente conhece sobre classes abstratas, as quais ele não pode instanciar... Solução: Factory Method. Encapsula o conhecimento de qual subclasse Document criar e move este conhecimento para fora do framework A subclasse de Application redefine uma operação de criação abstrata (Factory Method) e retorna a subclasse Document apropriada. 7 Motivação 2 8 4
Aplicação Use Factory Method quando: Uma classe não pode antecipar a classe dos objetos que ela deve criar Uma classe quer que suas subclasses especifiquem os objetos que elas criam 9 Estrutura 10 5
Participantes Product (Document) Define a interface dos objetos que o método fábrica (Factory Method) cria ConcreteProduct (MyDocument) Implementa a interface de Product 11 Participantes Creator (Application) Declara o método fábrica, o qual retorna um objeto do tipo Product. Creator também pode definir uma implementação default do método fábrica, que retorne um objeto ConcreteProduct padrão Pode chamar o método fábrica para criar um objeto Product ConcreteCreator (MyApplication) Sobrescreve o método fábrica para retornar uma instância de um ConcreteProduct 12 6
Colaborações Creator confia a suas subclasses a definição do método fábrica, para que ele retorne uma instância do ConcreteProduct apropriado 13 Solução Motivação 1: Modelo UML com padrão Factory Method Acionador Impl. Factory Hierarquia Cliente A Classe Creator possui a implementação na qual reside o método factory, que decide qual das sub-classes deve ser instanciada 7
Conseqüências 1. Elimina a necessidade de ligar o código a classes específicas da aplicação 2. Provê ganchos (hooks) para especialização (versão estendida de um objeto) 3. Desvantagem potencial: eventualmente, clientes podem ter que especializar a classe Creator apenas para criar um objeto ConcreteProduct particular (um ponto de evolução adicional) 15 Conseqüências 4. Conecta hierarquias de classes paralelas (quando uma classe delega algumas de suas responsabilidades a outra) 16 8
Conseqüências Diferentes figuras usam diferentes subclasses Manipulator para tratar interações particulares Note que o método fábrica define uma conexão entre as duas classes de hierarquia. Ele detém o conhecimento de quais classes se co-relacionam. 17 Exemplo: Diagrama de Classes Acionador Hierarquia Cliente Impl. Factory 9
Exemplo: Diag Seqüência Implementação Duas variantes principais: Quando a classe Creator é uma classe abstrata e não provê uma implementação para o método fábrica que ela declara Contorna dilema de se ter que instanciar classes imprevisíveis Quando Creator é uma classe concreta e provê uma implementação default para o método fábrica Regra: Crie objetos em uma operação separada para que as subclasses possam sobrescrever a forma como eles são criados 20 10
Implementação Outra: Métodos fábrica parametrizados 21 Implementação Sobrescrever métodos fábrica parametrizados é uma forma fácil e seletiva de se estender ou mudar os produtos criados (pode-se introduzir novos identificadores ou mudar os já existentes) 22 11
Implementação Questões específicas de linguagem Em C++, métodos fábricas são sempre funções virtuais (ou virtuais puras). Cuidado para não chamá-la do construtor da classe criadora (Creator), pois o método fábrica na classe concreta pode não estar pronto ainda. Pode-se evitar isto através da técnica lazy initialization: acesse produtos através de operações de acesso que criem o produto sob demanda (o construtor apenas inicializa o produto com zero) 23 Implementação 24 12
Implementação Use templates para evitar subclasses (especialização) 25 Implementação Por fim, uma convenção de nomes Sempre deixe claro que você está usando um método fábrica (P.ex.: DoMakeDoc(), FactoryDoc() etc) 26 13
Exemplo 27 Exemplo 28 14
Exemplo Jogos diferentes podem especializar partes do labirinto. As subclasses de MazeGame podem redefinir alguns ou todos os métodos fábrica para especificar variações dos produtos 29 Exemplo 30 15
Exemplo 31 Exemplo Para criar um labirinto que contenha cômodos encantados, basta chamar CreateMaze de um EnchantedMazeGame: EnchantedMazeGame game; game.createmaze(); 32 16