Decorator POO - Avançado.

Slides:



Advertisements
Apresentações semelhantes
Classes Abstratas e Interfaces
Advertisements

Modificadores Marco Antonio. Introdução Em todas as linguagens de programação o acesso a classes/métodos deve seguir algumas regras.
Java Básico Orientação a Objeto Marco Antonio Software Architect Fev/2008.
Herança, Polimorfismo e Classes Abstratas em Java
Projeto de Sistemas de Software Hazel, Juliana e Luana
De 17 1 Linguagens de Programação Orientadas a Objetos Pós-Gradução(Lato-Sensu) em Sistemas de Banco de Dados - UFPa Marco Fagundes Aula.
Generalização, Especialização e Conceitos
Iniciação ao Java – Márcio F. Campos
Refatorações Experiência é aquela coisa maravilhosa que permite que você reconheça um erro tão logo o cometa novamente F.P. Jones.
1 Introdução aos padrões de projeto (GoF) Conceitos preliminares –Mecanismos de herança –Princípio de Substituição de Liskov –Acoplamento concreto x Acoplamento.
Padrões GoF – Factory Method
Polimorfismo e Classes Abstratas Profa
Introdução ao paradigma de programação: Orientado a Objetos
Wagner Santos C. de Jesus
UMA ABORDAGEM SOBRE ORIENTAÇÃO A OBJETOS!
Classes e objetos P. O. O. Prof. Grace.
Revisão POO Profa. Cintia Carvalho Oliveira
Strategy e Template Method
Unidade I: “Dê um mergulho rápido”
Programação Orientada a Objetos com Java
Nazareno Andrade (baseado no material de Hyggo Almeida)
Singleton e Adapter Professor: Nazareno Andrade
Treinamento do Microsoft® Access® 2010
Programação I Aula 2 (Métodos)
Linguagem de Programação JAVA
Paulo Borba Centro de Informática Universidade Federal de Pernambuco Classes Abstratas e Interfaces.
Professora Lucélia Oliveira
Paulo Borba Centro de Informática Universidade Federal de Pernambuco
Curso de Aprendizado Industrial Desenvolvedor WEB Disciplina: Programação Orientada a Objetos I Professora: Cheli Mendes Costa This.
Programação Orientada à Objetos
Curso de Aprendizado Industrial Desenvolvedor WEB Disciplina: Programação Orientada a Objetos I Professora: Cheli Mendes Costa Membro Static.
Acoplamento e Coesão Modelagem e Programação Orientada a Objetos
Curso de Aprendizado Industrial Desenvolvedor WEB Disciplina: Programação Orientada a Objetos I Professora: Cheli Mendes Costa Classes e Objetos em Java.
Filter Design Pattern.
Wagner Santos C. de Jesus
Aula prática 14 Orientação a Objetos – C++ Parte 2
Programação Orientada a Objetos - Java
Programação Orientada a Objetos - Java Professor: Jean Carlo Mendes.
Programação Orientada à Objetos
Curso de Aprendizado Industrial Desenvolvedor WEB
UTFPR – Campus Curitiba - DAELN Cursos de Eng. Eletrônica/Eng
Prof. Gilberto Irajá Müller
Orientação a Objetos usando Java
Aula Prática 4 Monitoria IP/CC (~if669).
Polimorfismo.
POO II JEAN CARLO MENDES
Orientação a Objetos e Java Graduação em Ciência da Computação  Centro de Informática, UFPE Alexandre Mota
Interfaces POO Avançado.
Classes Abstratas e Interface
Programação Orientada a Objetos - Java Professor: Jean Carlo Mendes.
Modelando Sistemas em UML
Certificação Marco Antonio. Introdução A compreensão desse capítulo é muito importante pois trata de um assunto essencial em qualquer linguagem de programação,
Herança Modelagem e Programação Orientada a Objetos
Factory.
Padrões de projeto M.Sc. Sílvio Bacalá Jr..
Jobson Ronan Padrões GoF Jobson Ronan
Classes abstratas São classes das quais não se pode instanciar objetos. São classes das quais não se pode instanciar objetos. Seu objetivo é ser herdada.
2 – Revisão de Programação Orientada a Objetos
Módulo II Capítulo 1: Orientação a Objetos
Aula 5 – Padrão Decorator
Aula 6 – Padrão Factory Method
Padrões de Projeto Aula 9 – Padrão Adapter.
Aula 7 – Padrão Abstract Factory
UCSal – Bacharelado em Informática Tópicos Especiais em Informática II Profa. Semíramis Assis
Padrões de Projeto 2 – Revisão de Programação Orientada a Objetos.
Engenharia de Software Orientada a Objetos Professor: Guilherme Timóteo Aula 3: – Modelagem de Classes (parte 2)
Padrões de Projeto de Criação Padrões de Projeto Orientados a Objetos Prof a. Danielle Martin Universidade de Mogi das Cruzes.
Herança em Java Curso: Informática Disciplina: Programação Orientada a Objetos Prof. Abrahão Lopes
Padrões de Projeto Aula 5 – Padrão Decorator 1. QuickReview: Observer Definição: Quando usar? Tipo de padrão? Como? 2.
Linguagem de Programação – Aula 04 Prof. Me. Ronnison Reges Vidal.
Transcrição da apresentação:

Decorator POO - Avançado

O padrão Decorator e muito importante e muito utilizado também pela API Java. O padrão Decorator é utilizado quando precisa-se anexar responsabilidades dinamicamente sem precisar de uma grande hierarquia de subclasses.

Funcionamento A descrição original do Padrão Decorator é: "O Padrão Decorator anexa responsabilidades adicionais a um objeto dinamicamente. Os decoradores fornecem uma alternativa flexível de subclasse para estender a funcionalidade".

O Padrão Decorator tem como característica o seguinte: Os decoradores têm o mesmo supertipo que os objetos que eles decoram; Você pode usar um ou mais decoradores para englobar um objeto; Uma vez que o decorador tem o mesmo supertipo que o objeto decorado, podemos passar um objeto decorado no lugar do objeto original (englobado); O decorador adiciona seu próprio comportamento antes e/ou depois de delegar o objeto que ele decora o resto do trabalho; Os objetos podem ser decorados a qualquer momento, então podemos decorar os objetos de maneira dinâmica no tempo de execução com quantos decoradores desejarmos.

Exemplo Imagine que você está desenvolvendo um sistema para um bar especializado em coquetéis, onde existem vários tipos de coquetéis que devem ser cadastrados para controlar a venda. Os coquetéis são feitos da combinação de uma bebida base e vários outros adicionais que compõe a bebida. Por exemplo:

Exemplo Conjunto de bebidas: Cachaça Rum Vodka Tequila

Conjunto de adicionais: Limão Refrigerante Suco Leite condensado Gelo Açúcar

Então, como possíveis coquetéis temos: Vodka + Suco + Gelo + Açúcar Tequila + Limão + Sal Cachaça + Leite Condensado + Açúcar + Gelo E então, como representar isto em um sistema computacional?

Uma solução? Bom, poderíamos utilizar como uma solução simples uma classe abstrata Coquetel extremamente genérica e, para cada tipo de coquetel construir uma classe concreta. Então teríamos a classe base Coquetel:

public abstract class Coquetel {     String nome;     double preco;       public String getNome() {         return nome;     }     public double getPreco() {         return preco; }

A nossa classe define apenas o nome e o preço da bebida para facilitar a exemplificação. Uma classe coquetel concreta seria, por exemplo, a Caipirinha: public class Caipirinha extends Coquetel {     public Caipirinha() {         nome = "Caipirinha";         preco = 3.5;     } }

No entanto, como a especialidade do bar são coquetéis, o cliente pode escolher montar seu próprio coquetel com os adicionais que ele quiser. De acordo com nosso modelo teríamos então que criar várias classes para prever o que um possível cliente solicitaria! Imagine agora a quantidade de combinações possíveis? Veja o diagrama UML abaixo para visualizar o tamanho do problema:

Além disso, pode ser que o cliente deseje adicionar doses extras de determinados adicionais, desse modo não seria possível modelar o sistema para prever todas as possibilidades! Então, como resolver o problema?

Decorator Vamos ver qual a Intenção do padrão Decorator: “Dinamicamente, agregar responsabilidades adicionais a objetos. Os Decorators fornecem uma alternativa flexível ao uso de subclasses para extensão de funcionalidades.” [1] Queremos que, dado um objeto Coquetel, seja possível adicionar funcionalidades a ele, e somente a ele, em tempo de execução. Vamos ver a arquitetura sugerida pelo padrão:

Todos os objetos possuem o mesmo tipo Coquetel, esta classe define o que todos os objeto possuem e é igual a classe já feita antes. As classes de bebidas concretas definem apenas os dados relativos a ela. Como exemplo vejamos o código da bebida Cachaça:

public class Cachaca extends Coquetel {     public Cachaca() {         nome = "Cachaça";         preco = 1.5;     } }

Todas as classes de bebidas possuirão a mesma estrutura, apenas definem os seus atributos. A classe Decorator abstrata define que todos os decoradores possuem um objeto Coquetel, ao qual decoram, e um método que é aplicado a este objeto.

public abstract class CoquetelDecorator extends Coquetel {     Coquetel coquetel;       public CoquetelDecorator(Coquetel umCoquetel) {         coquetel = umCoquetel;     }     @Override     public String getNome() {         return coquetel.getNome()  + " + " + nome;     public double getPreco() {         return coquetel.getPreco() + preco; }

Lembre-se de que como o decorador também é um Coquetel ele herda os atributos nome e preço. Nas classes concretas apenas definimos os modificadores que serão aplicados, de maneira semelhante as classes de bebidas concretas, vejamos o exemplo do adicional Refrigerante:

public class Refrigerante extends CoquetelDecorator { public Refrigerante(Coquetel umCoquetel) { super(umCoquetel); nome = "Refrigerante"; preco = 1.0; } }

Perceba que no construtor do decorador é necessário passar um objeto Coquetel qualquer, este objeto pode ser tanto uma bebida quanto outro decorador. Ai está o conceito chave para o padrão Decorator. Vamos acrescentando vários decoradores em qualquer ordem em uma bebida. Vamos ver agora como o padrão seria utilizado, veja o seguinte código do método main:

public static void main(String[] args) {         Coquetel meuCoquetel = new Cachaca();         System.out.println(meuCoquetel.getNome() + " = "                 + meuCoquetel.getPreco());           meuCoquetel = new Refrigerante(meuCoquetel);     }

Perceba que o tipo do coquetel varia de acordo com o decorador aplicado. Então, quando chamamos o método getNome ou getPreco o primeiro método chamado é o método do último decorador aplicado. O método do decorador por sua vez chama o método da classe mãe, este método então chama o método do Coquetel ao qual ele decora. Se esse coquetel for outro decorador o pedido é repassado até chegar a um coquetel que é uma bebida de fato e finalmente responde a requisição sem repassar a nenhum outro objeto.

De maneira semelhante a recursão, os valores calculados vão sendo retornados até chegar no último decorador aplicado e então são repassados ao objeto. É como se os decoradores englobassem tanto outros decoradores quanto o componente em si.

Teoria Como já dito o padrão Decorator adiciona funcionalidades ao objeto em tempo de execução. Note bem que, ao contrário da herança que aplica funcionalidades a todos os objetos dela, o padrão decorator permite aplicar funcionalidades apenas a um objeto específico. Justamente devido a essa propriedade é que o padrão Decorator possui uma flexibilidade maior que a herança estática. Além disso, como o Decorator aplica apenas as funcionalidades necessárias ao objeto nós evitamos o problema de classes sobrecarregadas, que possuem funcionalidade que nunca são utilizadas.

Problemas No entanto este comportamento altamente dinâmico do Decorator traz alguns problemas, como por exemplo, dado um objeto Coquetel não é possível verificar se ele possui um decorador Limão, Refrigerante ou qualquer outro. Assim, caso cada um dos decoradores implementasse outros métodos específicos, um desenvolvedor que utilizasse um coquetel qualquer não possui nenhuma garantia sobre o tipo do coquetel. Por exemplo, se o decorador Limão implementa um método azedo(), não é possível afirmar que um coquetel qualquer possui este método.

Problemas O problema é pior ainda pois não é possível sequer verificar o tipo do coquetel, por exemplo, adicione este código no final do método main: System.out.println(meuCoquetel instanceof Cachaca);

Problemas Será exibido no console “false” pois, como aplicamos o decorador Refrigerante modificamos o tipo do coquetel. Além disso é necessário criar vários pequenos objetos, que possuem o mesmo comportamento, para criar os coquetéis necessários. No primeiro modelo apresentado teríamos várias classes, mas apenas um objeto para representar um Coquetel. Utilizando a estrutura do Decorator precisamos criar um objeto para cada novo decorador, além do objeto bebida.

Conclusão Como pode-se notar neste artigo, o padrão Decorator usa a herança apenas para ter uma correspondência de tipo e não para obter o comportamento. Assim, quando compõe-se um decorador com um componente, adiciona-se um novo comportamento, nota-se que estamos adquirindo um novo comportamento e não herdando-o de alguma superclasse. Isso nos dá muito mais flexibilidade para compor mais objetos sem alterar uma linha de código, tudo em tempo de execução e não em tempo de compilação como ocorre com a herança. Todos esses benefícios nos são disponibilizados pelo uso do padrão Decorator. Uma desvantagem do padrão é que teremos inúmeras classes pequenas que pode ser bastante complicado para um desenvolvedor que está tentando entender o funcionamento da aplicação. Assim, precisamos avaliar esses casos e optar por uma solução que de repente não seja usando decoradores.

Bibliografia Eric Freeman, Elisabeth Robson, Bert Bates, Kathy Sierra. Head First Design Patterns. O'Reilly Media, 2004. [1] GAMMA, Erich et al. Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos.