Abstract Factory Pattern
SISMO - Sistemas e Mobilidade http://www.sismo.deinf.ufma.br
Departamento de Inform´atica / UFMA
Junho de 2008
Comandar uma franquia n˜ao ´e bolinho
Estava tudo muito bom com a franquia PizzaRute, mas...
Alguns franqueados resolveram aumentar as margens de lucro usando ingredientes mais baratos e de baixa qualidade
E necess´´ ario garantir consistˆencia na qualidade os ingredientes usados pelas franquias
Como atacar esse problema?
Mantendo a consistˆencia dos ingredientes
A id´eia ´e criar uma f´abria (real) para produzir os ingredientes para todas as franquias
A f´abrica deve produzir e enviar os ingredientes aos franqueados
Por´em, existe um problema. Os ingredientes das pizzas s˜ao essencialmente os mesmos em cada regi˜ao, mas existem varia¸c˜oes espec´ıficas das diferentes regi˜oes. Por exemplo, o cheiro verde da regi˜ao sudeste tem salsa no lugar do coentro, o marisco em S˜ao Luis ´e diferente do marisco em S˜ao Paulo
Mantendo a consistˆencia dos ingredientes II
De um modo geral, cada regi˜ao (e as franquias regionais) usam uma fam´ılia de ingredientes espec´ıfico
Logo ser˜ao abertas novas franquias em Roraima e at´e no Caribe
E necess´´ ario definir um modo de lidar com essas diferentes fam´ılias de ingredientes
A f´abrica de ingredientes
A f´abrica ser´a respons´avel pela cria¸c˜ao deFam´ılias de Ingredientes
A id´eia de criar fam´ılias de ingredientes ´e manter a
consistˆencia do conjunto de ingredientes que satisfaz o gosto dos clientes da regi˜ao
N˜ao se deve permitir, por exemplo, misturar ingredientes da franquia gaucha com ingredientes da franquia bahiana
A F´abrica de Ingredientes
Figura: Interface para a F´abrica de Ingredientes
Implementando F´abricas de Ingredientes
Figura: F´abrica de Ingredientes da Franquia de S˜ao Paulo
Como fica a classe Pizza?
Figura: A nova classe Pizza
Uma Classe Pizza concreta
Figura: Uma classe concretaPizza de Mussarela
Analisando o c´odigo
molho = ingredienteFactory.createMolho();
A f´abrica de ingredientes agora ´e usada para produzir pizzas O tipo de ingrediente depende do tipo de f´abrica usada Se usarmos uma f´abrica de ingredientes de S˜ao Luis, ela produzir´a um molho do tipo consumido em S˜ao Luis
A pizza n˜ao sabe qual a f´abrica que est´a sendo usada, desde que ela seja uma f´abrica de ingredientes
Outra Classe Pizza concreta
Figura: Uma classe concretaPizza de Mariscos
Em S˜ao Luis, o marisco pode ser sarnambi. Quem decide ´e a f´abrica de ingredientes.
Como ficam as franquias?
Figura: Uma classe concretaFranquia de S˜ao Paulo
Compare com a implementa¸c˜ao Factory Method
Figura: Uma classe concretaFranquia de S˜ao Paulo - Vers˜ao anterior
As Principais Mudan¸cas
Possibilitou-se a cria¸c˜ao de uma fam´ılia de ingredientes para pizzas pela introdu¸c˜ao de uma novo tipo de f´abrica chamada Abstract Factory
Abstract Factory fornece uma interface para criar uma fam´ılia de produtos
No nosso exemplo, a fam´ılia de produtos ´e formada por todos os ingredientes b´asicos de uma pizza (massa, queijo, molho, etc.), os quais sempre devem andar juntos, como uma fam´ılia tradicional. O que muda ´e a implementa¸c˜ao das fam´ılias.
As Principais Mudan¸cas II
DaAbstract Factory derivamos f´abricas concretas
Cada f´abrica de ingredientes cria diferentes implementa¸c˜oes desses mesmos ingredientes ao implementar os m´etodos declarados na Abstract Factory
Nosso c´odigo ´e separado dos produtos reais Se substituirmos as f´abricas, obtemos fam´ılias
(implementa¸c˜oes) diferentes dos mesmos produtos. O que resulta em pizzas diferentes.
Fazendo um pedido
Precisamos inicialmente de uma franquia concreta PizzaRute spPizzaRute = new SampaPizzaRute();
Agora que temos uma franquia, podemos fazer um pedido spPizzaRute.pedidoPizza(“mussarela”);
O m´etodo pedidoPizza()chama o m´etodocreatePizza() pizza = createPizza(tipo);
Fazendo um pedido - continuando
No m´etodo createPizza(), a f´abrica de ingredientes ´e passada para o construtor de Pizzas
pizza = new PizzaMussarela(ingredientFactory);
O m´etodo prepare(), implementado nas classes Pizza concretas, usa a f´abrica de ingredientes para criar cada ingrediente da pizza, de acordo com a fam´ılia dele
massa = ingredienteFactory.createMassa();
Finalmente, o m´etodo pedidoPizza()chama os outros m´etodos da Pizza para terminar o pedido (pizza.asse(), pizza.corte(), etc)
O Padr˜ao Abstract Factory
Classifica¸c˜ao:
Prop´osito: Criacional / Escopo: Objetos Inten¸c˜ao:
fornecer uma interface para criar fam´ılias de objetos relacionados ou dependentes sem especificar suas classes concretas.
aka: kit
Aplicabilidade
Quando usar o padr˜ao
Um sistema n˜ao deve depender de como seus produtos s˜ao criados, compostos e representados
Um sistema deve ser configurado como um produto de uma fam´ılia de muitos produtos
garantir que uma fam´ılia de objetos-produto seja usada em conjunto, se foi projetada com esse fim
Estrutura
Participantes
AbstractFactory: declara interface para opera¸c˜oes que criam objetos-produto abstratos
ConcreteFactory: implementa opera¸c˜oes que criam objetos-produto concretos
AbstractProduct: declara interface para um tipo de objeto-produto
ConcreteProduct:
define um objeto-produto a ser criado pela f´abrica concreta correspondente
implementa a interface de AbstractProduct
Colabora¸c˜oes
Normalmente uma ´unica instˆancia de uma classe ConcreteFactory ´e criada em tempo de execu¸c˜ao
AbstractFactory adia a cria¸c˜ao dos objetos produto para a classe ConcreteFactory
Consequˆencias
Isola as classes concretas (n˜ao aparecem no c´odigo do cliente) Facilita a troca de fam´ılia de produtos
Promove a harmonia entre produtos
E dif´ıcil suportar novos tipos de produtos (exige mudar a´ classe AbstractFactory e todas as suas subclasses)
Mais um Exemplo
Constru¸c˜ao de interfaces de usu´ario que suportem diferentes estilos de intera¸c˜ao, permitindo diferentes apresenta¸c˜oes e comportamentos para os widgets de cada estilo
As dependˆencias entre as classes concretas de widgets tamb´em precisam ser garantidas e implementadas
Estrutura do exemplo
Figura: Uma classe concretaFam´ılias de Widgets