Disseminar informação é preciso

Padrão de projetos Strategy na prática

| Junho 28, 2009


O Padrão de Projeto Strategy define uma família de algoritmos, encapsula cada algoritmo e os torna intercambiáveis, permitindo que o algoritmo varie independente dos clientes que o utilizam.

Essa é uma definição clássica e abstrata. Não se assuste se não entendeu nada. Realmente sem ter um exemplo prático fica muito difícil entender.

A idéia do post é justamente essa. Trazer uma abordagem prática para que o leitor possa de fato absorver e compreender esse padrão.

Imagine a classe documento abaixo:

package sem.strategy;

public abstract class Documento {

public void imprime(){

System.out.println("Documento impresso em Pdf");

}

}

Atualmente está preparada apenas para imprimir documentos em Pdf de forma padrão. Mais surgiu a necessidade de implementar diversos tipos de impressões de documentos, por exemplo: Pdf, Xml, Xls, HTml. E para piorar, a impressão de todos esses documentos pode ser feita de suas formas: com ou sem título.

A primeira idéia que a equipe de desenvolvimento teve foi encher a classe Documento de métodos para cada tipo de impressão. A cada novo método de impressão criado, a classe Documento teria que ser mantida. Outra desvantagem é que certos tipos de documentos poderiam ser impressos de formas diferentes, por exemplo: um documento Jurídico pode ser impresso de forma diferente de um documento Técnico.

Certo desenvolvedor, conhecia e decidiu usar o Padrão de Projeto Strategy (ou Estratégia).

A idéia foi tirar a regra de impressão de dentro da classe Documento, fazendo uso do Strategy.

Dessa forma foi criado a interface Imprime, que será nossa Estratégia, conforme abaixo:

package com.strategy;

public interface Imprime {

public void imprime();

}

Para o nosso exemplo vamos criar apenas duas classes que imprimem, Pdf e Xml:

package com.strategy;

public class Pdf implements Imprime {

@Override

public void imprime() {

System.out.println("Documento foi impresso em PDF!");

}

}

package com.strategy;

public class Xml implements Imprime {

@Override

public void imprime() {

System.out.println("Documento foi impresso em XML!");

}

}

Tivemos que fazem uma pequena alteração na classe Documento, ficando assim:

package com.strategy;

public abstract class Documento {

protected Imprime imprime;

public void imprime(){

imprime.imprime();

}

public void setImprime(Imprime imprime) {

this.imprime = imprime;

}

}

Veja que agora a classe Documento não conhece mais a forma de como o documento é impresso. Como podemos observar o método imprime, apenas faz a chamada ao método imprime da nossa Estratégia (interface) e não faz a menor idéia de como o documento será impresso.

Criamos um documento técnico:

package com.strategy;

public class Tecnico extends Documento {

}

Agora vamos criar uma classe cliente para testar o uso do nosso Padrão de Projeto:

package com.strategy;

public class Cliente {

public static void main(String[] args) {

Documento documento = new Tecnico();

documento.setImprime(new Pdf());

documento.imprime();

documento.setImprime(new Xml());

documento.imprime();

}

}

Rodando esse exemplo, esperamos como saída:

Documento foi impresso em PDF!

Documento foi impresso em XML!

Legal! Como podemos observar a forma como o documento é impressa pode ser alterada em tempo de execução.

O exemplo utilizado foi bem simples e apenas para fins didáticos, porém se a idéia foi absorvida você poderá acrescentar funcionalidades e alguns ajustes e conseqüentemente expandir e aplicar em situações do seu dia-a-dia.

Entendendo o Ciclo de Vida JSF

| Junho 25, 2009
A especificação JSF define seis fases, conforme a figura abaixo:














1. Restore view

Se a página requisitada já foi exibida antes, é recuperada toda a árvore de componentes para a página requisitada. Caso esteja sendo exibida pela primeira vez é construída uma nova árvore de componentes. No caso da página já ter sido exibida antes, todos os componentes serão configurados com seu estado anterior. É fácil notar isso no processo de validação, onde os valores digitados inicialmente no formulário serão mantidos.

Se a requisição não possuir dados solicitados, a implementação JSF pula para a fase Render Response. Normalmente isso acontece quando a página é requisitada a primeira vez.

2. Apply request values

Nesta fase ocorrem iterações sobre os objetos da árvore de componentes. São extraídos todos os valores digitados pelo usuário e guardados esses valores nos seus respectivos componentes.

3. Process validation

A String com o valor enviado é convertida para o tipo correto do objeto. Caso ocorra algum erro de validação mensagem de erro é adicionada no FacesContext, o componente é marcado como inválido e a implementação JSF invoca a fase Render Response. Caso contrário o ciclo de vida continua normalmente.

4. Update Model Values

Sua principal atividade é atribuir os valores informados pelo usuário no formulário, para as respectivas propriedades associadas aos BackBeans (também conhecidos como Managed Beans). Pode haver erro na conversão, fazendo com que o JSF dispare um erro de tempo de execução.

5. Invoke Application

Nesta fase o controlador (controller) do JSF chama o método associado no submit, disparando assim a camada de regras de negócio da aplicação. Todos os valores foram validados e carregados nas fases anteriores, por isso poderemos usá-los conforme necessitar. Geralmente é retornado uma String de resultado, que é passada para o handle de navegação.

6. Render Response

Esta fase codifica a resposta e envia-a de volta ao navegador.

A casa nova requisição o ciclo recomeça do zero.