Design Pattern: Implementando o Decorator

Posted by Alberto Leal on June 23rd, 2009

Photo: http://static.howstuffworks.com/gif/teen-bedroom-decorating-ideas-2.jpg

O último livro que terminei de ler era sobre Design Pattern. Então, resolvi fazer alguns posts contendo algumas implementações. O padrão de projeto da vez é o Decorator.

——–

O poder da composição

Têm quem ame, e têm quem odeie herança. Existem casos que não há como fugir da herança, mas, sempre que possível, prefira composição a herança. Quando utilizamos herança em uma parte da nossa aplicação, e alguns comportamentos são herdados, estes  são definidos estaticamente em tempo de compilação. Por outro lado, se você estender o comportamento de um objeto por meio de composição, você consegue fazer isso dinamicamente, ou seja, consegue compôr os objetos de forma dinâmica. Com isso, se torna fácil adicionar novas funcionalidades escrevendo um código novo ao invés de alterar o código existente. Isso é bacana, pois o comportamento anterior não é modificado, assim as chances de introdução de erros no código que já estava funcionando é menor. Se algo der errado, basta remover a nova classe que foi criada, por exemplo. Resumindo, mantenha as classes abertas para extensão e fechadas para alteração.

O padrão de projeto decorator anexa novas responsabilidades em um objeto dinamicamente, utilizando  do poder da composição.

Vamos ver como isso funciona na prática. O exemplo que lhe será apresentado é a construção de uma pizza. No momento do pedido, o cliente poderá pedir ao Pizzaiolo que adicione  novos ingredientes na pizza, tais como: orégano e tomate. Exemplo simples e direto, apenas para ilustrar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package br.eti.albertoleal.decorator;
 
public abstract class Pizza {
 
private String description = "Unknown Pizza";
 
public void setDescription(String desc) {
description = desc;
}
 
public String getDescription(){
return description;
}
 
public abstract double cost();
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package br.eti.albertoleal.decorator;
 
public class Cheese extends Pizza {
 
	public Cheese(){
		setDescription("Cheese Pizza")
	}
 
	@Override
	public double cost() {
		return 19.90;
	}
 
}

As classes decorator devem ser espelhos das classes que elas vão decorar. Vamos utilizar da herança em nossos objetos do tipo CondimentDecorator. O motivo de se usar herança na classe Decorator é  pelo simples fato de se ter o mesmo tipo dos objetos que vão ser decorados. O uso de herança é justamente para atingir  essa correspondência de tipo.

1
2
3
4
5
package br.eti.albertoleal.decorator;
 
public abstract class CondimentDecorator extends Pizza {
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package br.eti.albertoleal.decorator;
 
public class Oregano extends CondimentDecorator {
	Pizza pizza;
 
	public Oregano(Pizza pz) {
		pizza = pz;
	}
 
	@Override
	public String getDescription() {
		return pizza.getDescription() + ", Oregano";
	}
 
	@Override
	public double cost() {
		return .50 + pizza.cost();
	}
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package br.eti.albertoleal.decorator;
 
public class Tomato extends CondimentDecorator {
	Pizza pizza;
 
	public Tomato(Pizza pz){
		pizza = pz;
	}
 
	@Override
	public String getDescription() {
		return pizza.getDescription() + ", Tomato ";
	}
 
	@Override
	public double cost() {
		return .10 + pizza.cost();
	}
 
}

Se você estava atento reparou que a cada condimento que é adicionado na pizza um valor correspondente ao condimento é somado ao valor da pizza. Essa é a idéia do decorator. Estou decorando um objeto pizza com diversos outros componentes. Um outro exemplo, bastante comum de se encontrar pela internet, são as janelas gráficas. O ato de decorar uma janela gráfica com diversos componentes de apresentação, tais como: barra de rolagem, campos de texto e por aí vai.

Chegou a hora de testarmos o nosso código, criar uma pizza e adicionar alguns condimentos a ela e constatar se a nossa “decoração” funciona:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package br.eti.albertoleal.decorator;
 
public class Pizzaiolo {
 
	public static void main(String[] args) {
 
		Pizza pz = new Cheese();
 
		pz = new Tomato(pz);
		pz = new Tomato(pz);
		pz = new Oregano(pz);
		pz = new Tomato(pz);
		pz = new Oregano(pz);
		pz = new Tomato(pz);
 
		System.out.println(pz.getDescription());		
 
	}
 
}

Concluindo:

  • A herança é uma maneira de estender comportamentos, mas não é a melhor maneira de obter flexibilidade;
  • Composição e delegação são boas maneiras de se adicionar funcionalidades em tempo de execução;
  • A utilização de um componente decorator é simplesmente decorar um objeto, e o objeto decorado não precisa conhecer os decoradores;
  • É muito importante que os objetos decoradores sejam espelhos do objeto que vão decorar, justamente para ter uma correspondência de tipo.

Livro: My job went to India

Posted by Alberto Leal on June 15th, 2008

Este foi um dos melhores livros que eu li nos últimos tempos. Se você está procurando alguma coisa para ler, mas não sabe o que, aqui está minha sugestão. Você Programador, você Analista, você Gerente, VOCÊ PRECISA ler este livro.

Trata-se de um livro que, ao meu ver, todos os programadores deveriam ler. Especialmente os inciantes.

É impressionante como o autor é claro e direto em suas colocações. Não é esforço nenhum ler livros como este. Parece que o autor está falando diretamente para você. É como conversar com um profissional mais experiente.

Segundo Fowler, a melhor forma de melhorarmos a nossa vida profissional é nos tornando empresário. Não necessariamente abrir uma empresa. Todos nós podemos ser empresários, desde que tenhamos espírito empreendedor em cada coisa que fizermos. E, para isso devemos nos orgazinar, operacionalizar (tomar iniciativas) e assumir riscos (não ter medo de tentar coisas novas).

Após alguns anos trabalhando com diferentes tipos de desenvolvedores, Fowler viu que alguns deles estavam entregando as suas vidas à empresas que sequer eram funcionários. Ao questionar um programador sobre o que ele gostaria de fazer, como gostaria de construir a sua carreira, ele ficou bastante surpreendido com a resposta: “Quero ser um arquiteto J2EE”. Tecnologia é uma coisa que muda constantemente, e muito rápido. Não podemos nos entregar totalmente a uma tecnologia mantida por outra empresa. Não se sabe por quanto tempo ela estará no mercado. Devemos estar atentos a tudo que acontece ao nosso redor.

A analogia, muito bem empregada diga-se de passagem, apresentada é: “Não coloque todos os seus ovos em um único cesto.” A tecnologia que usamos hoje pode ser a líder de mercado. Mas, e amanhã? Temos que estar sempre investindo em nosso conhecimento, sempre procurando novas tecnologias. E se for open-source, melhor ainda.

Seguindo mais adiante no livro, uma frase que me chamou bastante atenção foi a seguinte:

“The people around you affect your own performance. Choose your crowd wisely.”
“As pessoas que estão à sua volta afetam seu próprio desempenho. Escolha o seu grupo sabiamente.”

Não há quem discorde da frase acima. O interessante é a forma como ela foi tratada no livro. A frase está no capítulo 8: “Seja o Pior”. Em um primeiro momento o título parece estranho, já que queremos sempre ser os melhores naquilo que estamos nos propondo a fazer. Mas o autor explica: Quando somos os piores, quer dizer que estamos rodeados por pessoas inteligentes, espertas. E, a partir do momento em que estamos inseridos em um ambiente com tais pessoas, com o passar do tempo parece que estamos escrevendo/lendo melhor, codificando melhor. Não é simplesmente como um passo de mágica, e sim, porque quando em convivência, a tendência natural das pessoas é seguir o mesmo caminho das demais e aprender com elas.


Copyright © 2007 Alberto Leal. All rights reserved.