Padrões de ProjetoAula 6 – Padrão Factory Method
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
PADRÃO FACTORY
Sobre delegar as criações de objetos para fábricas.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Um dos principais princípios
Programe para interfaces/superclasses.
Por que?
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Pizzaria Sapore Rio Tinto
• Para entendermos o padrão Factory, vamos implementar um sistema para a pizzaria Sapore Rio Tinto. Para fazer uma pizza, nós basicamente a preparamos, assamos, fatiamos e a embalamos.
Pizza orderPizza(){Pizza pizza = new Pizza();
pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;
}
Programando para superclasses.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
• Mas a Sapore Rio Tinto vai vender mais do que um tipo de pizza...
Pizza orderPizza(String type){Pizza pizza;if(type.equals("Moussarela"))
pizza = new Moussarela();else if(type.equals("Pepperoni"))
pizza = new Pepperoni();else if(type.equals("Franpiry"))
pizza = new Franpiry();
pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;
}
agora estamos passando o tipo de Pizza
com base no tipo de pizza, instanciamos a classe concreta
Quando tivermos uma pizza iremos prepará-la, assá-la, fatiá-la e embalá-la. Cada subtipo de pizza sabe como se preparar (Strategy).
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
A Franpiry não está saindo muito... Vamos tirá-la do cardápio e adicionar a Marguerita.
Pizza orderPizza(String type){Pizza pizza;if(type.equals("Moussarela"))
pizza = new Moussarela();else if(type.equals("Pepperoni"))
pizza = new Pepperoni();else if(type.equals("Franpiry"))
pizza = new Franpiry();else if(type.equals(“Margherita"))
pizza = new Margherita();
pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;
}
Isto varia na medida em que o cardápio muda.
Isto esperamos que fique igual. Toda pizza passa pelo mesmo processo.
Isto não é nada bom!
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Outro princípio
Identifique os aspectos de seu sistema que variam e separe-os dos que permanecem iguais.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Aplicando o princípio...
Pizza orderPizza(String type){Pizza pizza;
pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;
}if(type.equals("Moussarela"))
pizza = new Moussarela();else if(type.equals("Pepperoni"))
pizza = new Pepperoni(); else if(type.equals(“Margherita")
pizza = new Margherita();
SimplePizzaFactory
Colocamos esse código em uma classe que só vai se preocupar em como criar pizzas. Se qualquer outro objeto quiser criar uma pizza ele deve recorrer a esta classe.
Não resolve 100% dos nossos problemas mas estamos no caminho certo... Aumentamos, um pouquinho, a coesão do sistema.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
public class SimplePizzaFactory {public Pizza createPizza(String type){
Pizza pizza = null;if(type.equals("moussarela"))
pizza = new Moussarela();else if(type.equals("margherita"))
pizza = new Margherita();else if(type.equals("pepperoni"))
pizza = new Pepperoni();return pizza;
}}
Vantagens: maior coesão e manutenção mais fácil
Vários clientes podem usar a fábrica e as alterações ficam localizadas no código encapsulado.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
public class PizzaStore {private SimplePizzaFactory pizzaFactory;public PizzaStore(SimplePizzaFactory pizzaFactory)
{this.pizzaFactory = pizzaFactory;
}public Pizza orderPizza(String type, int slices){
Pizza pizza = pizzaFactory.createPizza(type);pizza.prepare();pizza.bake();pizza.cut(slices);pizza.box();return pizza;
}}
agora PizzaStore tem uma referência a SimplePizzaFactory
PizzaStore recebe a fábrica no construtor
O método orderPizza agora usa a fábrica para criar suas pizzas
Note que agora não existe mais o modificador new. As instanciações concretas ficam na fábrica.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
The Simple Factory
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Considerações sobre a Simple Factory
• Não é um padrão, é um programming idiom. (Mais sobre programming idioms aqui)
• É legal pois torna nosso código coeso e centraliza possíveis alterações futuras em um único lugar, mas não resolve todos os problemas de flexibilidade
• Para isto, devemos recorrer a um dos seguintes padrões: Factory Method e Abstract Factory
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Franqueando a Sapore RT• A Sapore RT foi um sucesso! Agora queremos abrir novas franquias em João Pessoa e
em Campina Grande. Como franqueador devemos garantir a qualidade de nosso produto, portanto, queremos que cada franquia use nosso código testado e aprovado.
• Mas, devido às diferenças culturais, cada franquia pode querer oferecer estilos diferentes de pizza, dependendo de onde a loja esteja e do gosto dos apreciadores locais de pizza.
• Sugestões de design?
Massa média, molho temperado e muito queijo.
RioTintoFactory
JoaoPessoaFactory
Massa fina, molho temperado e pouco queijo.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
• Problems?• Uma SimpleFactory pode ser utilizada com outra Store, outra classe que não a
PizzaStore.• Logo, não há garantia que as franquias sigam o modelo de pizzaria proposto
pelas pizzarias Sapore. As outras franquias poderiam, por exemplo: assar de modo diferente, esquecer de fatiar a pizza, embalar com caixas de terceiros.
• Isso não é o que queremos. Isto descaracteriza a ideia de uma franquia... A classe PizzaStore e a criação das pizzas não estão mais acopladas como o esperado. Esse é um dos poucos casos em que o acoplamento se faz necessário.
• Para este caso nós desejamos o acoplamento (para garantir que as franquias sigam os mesmos processos com a alta qualidade das Pizzarias Sappore) mas também a flexibilidade (para que seja possível criar diferentes fábricas com diferente peculiaridades regionais).
RioTintoFactory rtFactory = new RioTintoFactory();PizzaStore rtStore = new PizzaStore(rtFactory);rtStore.order("Moussarela");
JoaoPessoaFactory jpFactory = new JoaoPessoaFactory();PizzaStore jpStore = new PizzaStore(jpFactory);jpStore.order("Moussarela");
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
• Pensando abstratamente, não há um acoplamento entre a classe que usa a fábrica (PizzaStore) e a própria fábrica.
• Como contornar este problema?• A SimpleFactory tornou o código da pizzaria fechado a
modificações mas quebrou o vínculo entre a Pizza e a Pizzaria.
• Vamos criar um forma de estabelecer um vínculo entre a Pizzaria e a forma de instanciar as pizzas mas mantendo a flexibilidade.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
The Method Factory Pattern
public abstract class PizzaStore {public Pizza orderPizza(String type, int slices){
Pizza pizza = createPizza(type);pizza.prepare();pizza.bake();pizza.cut(slices);pizza.box();return pizza;
}
protected abstract Pizza createPizza(String type);}
agora PizzaStore é abstrata createPizza volta para PizzaStore, ao invés de estar num objeto de fábrica
A criação do objeto de fábrica fica por conta deste método, o método Factory. Cabe às subclasses decidirem o que de fato é instanciado.
Perceba que PizzaStore é fechado para modificação mas flexível. Por que?
As novas lojas não interferem no restante do processo.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Franquias Sapore• As subclasses de PizzaStore (as franquias) é que decidem quais
tipos de Pizzas criar• Mas a forma do pedido da pizza segue o padrão estabelecido
para todas as franquias (ver método orderPizza)• orderPizza é um método cliente do instanciador createPizza
Cada franquia cria uma classe concreta que implementa createPizza Produto abstrato
Exemplo de produto concreto
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Definição• Todos os padrões factory encapsulam a criação de objetos;• O padrão Factory Method encapsula a criação de objetos
deixando as subclasses decidirem quais objetos criar;• Utilize o padrão quando uma classe precisa instanciar
subclasses de uma classe C que ainda não foram definidas;• Utilize esse padrão quando precisar delegar a
responsabilidade de criar objetos.O padrão Factory Method define uma
interface para criar um objeto, mas permite às classes decidir qual classe instanciar.
O Factory Method permite uma classe delegar a instanciação para subclasses.
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Terminologia e Estrutura
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Prática• Chega de blablabla... Vamo botar a mão na massa! • Vamos implementar o sistema da Sapore Pizzaria.• Considere as seguintes especificações:
Sabor Rio Tinto João Pessoa
Margherita Manjericão, massa média, muito queijo, molho temperadoTempo de forno: 7Temperatura: 550ºC
Manjericão, massa fina, pouco queijo, molho temperadoTempo de forno: 10Temperatura: 500ºC
Pepperoni Pepperoni, muito queijo, molho apimentadoTempo de forno: 10Temperatura: 500ºC
Pepperoni, muito queijo, molho apimentadoTempo de forno: 10Temperatura: 500ºC
Moussarela Muito queijoTempo de forno: 10Temperatura: 500ºC
Pouco queijoTempo de forno: 8Temperatura: 450ºC
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Padr
ões d
e Pr
ojet
o - F
acto
ry M
eth
od
Referências• [1] O cenário de pizzarias é abordado no capítulo 4 do livro
“Padrões de Projeto – Use a Cabeça!”