A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Adapter Definição: Quando usar? Tipo de padrão? Como?

Apresentações semelhantes


Apresentação em tema: "Adapter Definição: Quando usar? Tipo de padrão? Como?"— Transcrição da apresentação:

1 Adapter Definição: Quando usar? Tipo de padrão? Como?
- Def: O padrão Adapter converte a interface de uma classe para outra interface que o cliente espera encontrar. O Adaptador permite que classes com interfaces incompatíveis trabalhem juntas. - Quando usar? Interfaces incompatíveis. Tipo? Estrutural Como? Object Adapter (através de composição) e Class Adapter (herança múltipla (interface + herança))

2 Instanciando objetos inteligentemente!
POO Factory (Method) Prof. Eduardo Falcão

3 Padrão Factory Sobre delegar as criações de objetos para fábricas.

4 Um dos principais princípios
Programe para interfaces/superclasses. Por que esse princípio é tão importante? Resp.: só assim conseguimos praticar o polimorfismo. Por que?

5 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.

6 Mas a Sapore Rio Tinto vai vender mais do que um tipo de pizza...
agora estamos passando o 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; } com base no tipo de pizza, instanciamos a classe concreta Com esse cenário e com esse código, dá pra a gente ter noção que está sendo aplicado um padrão que nós já estudamos... O Strategy.  Quando tivermos uma pizza iremos prepará-la, assá-la, fatiá-la e embalá-la. Cada subtipo de pizza sabe como se preparar (Strategy).

7 A Franpiry não está saindo muito
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 não é nada bom! Por que isto não é bom? Estamos violando o princípio aberto fechado. As classes devem estar abertas para extensão mas fechadas para modificação. No nosso caso, nós mudaremos esse código com alguma frequência. Isso é modificação e não extensão. Isto esperamos que fique igual. Toda pizza passa pelo mesmo processo.

8 Outro princípio Identifique os aspectos de seu sistema que variam e separe-os dos que permanecem iguais. Por que esse princípio é tão importante? Resp.: assim conseguimos isolar as partes do código que sofrem mudanças. Identificando o que varia, podemos buscar algum padrão que resolva o problema eliminando ou diminuindo a ocorrência de mudanças no código.

9 Aplicando o princípio... Pizza orderPizza(String type){ Pizza pizza;
pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } 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. SimplePizzaFactory Essa classe encarregada de criar objetos sempre é chamada de Factory. if(type.equals("Moussarela")) pizza = new Moussarela(); else if(type.equals("Pepperoni")) pizza = new Pepperoni(); else if(type.equals(“Margherita") pizza = new Margherita(); Não resolve 100% dos nossos problemas mas estamos no caminho certo... Aumentamos, um pouquinho, a coesão do sistema.

10 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; } Até aqui, só orderPizza utilizaria o método createPizza. Mas se criássemos uma outras classes PizzaShopMenu e HomeDelivery, elas reutilizariam esse código. Quando houvesse alteração, apenas um lugar seria mudado, ao invés de três. 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.

11 Só é possível “herdar” e sobrescrever métodos de instância
Só é possível “herdar” e sobrescrever métodos de instância. Porém, esse método é visível nas sub-classes (há uma diferença entre herdar e ser visível).

12 agora PizzaStore tem uma referência a SimplePizzaFactory
PizzaStore recebe a fábrica no construtor 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; 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.

13 The Simple Factory

14 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 A Factory, por si só, não é um padrão de projeto. É um programming idiom. Eu diria que seria uma boa prática. Generally speaking, a programming idiom is an expression of a simple task, algorithm, or data structure that is not a built-in feature in the programming language being used, or, conversely, the use of an unusual or notable feature that is built into a programming language.

15 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? Mussarela: massa média, molho temperado e muito queijo. Uma solução seria utilizar fábricas diferentes... RioTintoFactory Mussarela: massa fina, molho temperado e pouco queijo. JoaoPessoaFactory

16 Problems? RioTintoFactory rtFactory = new RioTintoFactory();
PizzaStore rtStore = new PizzaStore(rtFactory); rtStore.order("Moussarela"); JoaoPessoaFactory jpFactory = new JoaoPessoaFactory(); PizzaStore jpStore = new PizzaStore(jpFactory); jpStore.order("Moussarela"); 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 não é mais um modelo que serve como base para todas as franquias. Ex.: outra loja poderia criar sua própria PizzaStore que asse de modo diferente, fatia a pizza em apenas 3 pedaços (não importando o tamanho da pizza), embale com caixas de baixa qualidade. Na verdade, queremos criar uma moldura que amarre à Loja à criação de Pizzas, para garantir que as franquias sigam os mesmos processos com a alta qualidade das Pizzarias Sappore. Porém, também desejamos que esta moldura proporcione flexibilidade (para que seja possível criar diferentes fábricas com diferentes peculiaridades regionais).

17 Como contornar este problema?
Pensando abstratamente, não há um acoplamento entre a PizzaStore (classe que usa a fábrica) e a própria fábrica. O acoplamento neste caso (apenas neste caso) é importante para garantir que a PizzaStore seja uma moldura para a criação de pizzas. Como contornar este problema? Vamos criar um forma de estabelecer um vínculo entre a Pizza (PizzaStore) e a forma de instanciar as pizzas mas mantendo a flexibilidade.

18 The Method Factory Pattern
agora PizzaStore é abstrata createPizza volta para PizzaStore, ao invés de estar num objeto de fábrica 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); As novas lojas não interferem no restante do processo. Perceba que PizzaStore é fechado para modificação mas aberto para extensão. Por que? Não é mais preciso alterar PizzaStore para criar novas Pizzas ou novas lojas. Ao criar novas lojas, por herança, cada uma decide como cada pizza deve ser criada mas não interferem no restante do processo. A criação do objeto de fábrica fica por conta deste método, o Factory method. Cabe às subclasses decidirem o que de fato é instanciado.

19 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 Perceba que PizzaStore nunca é mudada e nós conseguimos adicionar novas maneiras de criar pizzas, isso é flexibilidade e extensibilidade. Na nossa logística da PizzaSapore, poderíamos entregar todo o restante do código compilado (Sapore.jar), e garantir que o business model das pizzarias Sapore é seguido em todas as franquias. Cada franquia somente herdaria PizzaStore e forneceria a implementação do método de fábrica, createPizza. Exemplo de produto concreto

20 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 as classes decidir qual classe instanciar. O Factory Method permite uma classe delegar a instanciação para subclasses. Vocês precisam entender essa definição. Se tiverem dúvidas me avisem.

21 Terminologia e Estrutura
Product  pizza ConcreteProduct  diferentes tipos de pizza Creator  loja abstrata/ pizzaStore ConcreteCreator  diferentes tipos de loja para cada região

22 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 temperado Tempo de forno: 7 Temperatura: 550ºC Manjericão, massa fina, pouco queijo, molho temperado Tempo de forno: 10 Temperatura: 500ºC Pepperoni Pepperoni, muito queijo, molho apimentado Moussarela Muito queijo Pouco queijo Tempo de forno: 8 Temperatura: 450ºC

23

24 Referências [1] O cenário de pizzarias é abordado no capítulo 4 do livro “Padrões de Projeto – Use a Cabeça!”


Carregar ppt "Adapter Definição: Quando usar? Tipo de padrão? Como?"

Apresentações semelhantes


Anúncios Google