Você está na página 1de 14

Padres Arquiteturais no Java EE 7

Vagner F. Le Roy Jnior


Curso de Ps Graduao em Arquitetura de Software Distribudo
Pontifcia Universidade Catlica de Minas Gerais Belo Horizonte, MG Brasil
vagnerleroy@gmail.com

Abstract. This article seeks to analyze and demonstrate, through UML


diagrams and source code, applying design patterns in the architecture of
Java EE7.
Resumo. Este artigo busca analisar e demonstrar, por meio de diagramas
UML e cdigos fonte, a aplicao de padres de projeto na arquitetura do
Java EE7.

1. Introduo
Projetar sistemas orientados a objetos difcil e projetar sistemas orientados a objetos
reutilizveis ainda mais difcil. Os padres de projeto vm facilitar o desenvolvimento
de software oferecendo solues j testadas para problemas recorrentes no
desenvolvimento de software. Os padres conhecidos como Gof (Gangue dos quatro)
ficaram mundialmente conhecidos aps a publicao do livro Design Patterns: Elements
of Reusable Object-Oriented Software publicado em 1995 pelos autores Erich Gamma,
Richard Helm, Ralph Johnson e John Vlissides.
De acordo com Christopher Alexander, todo padro deve ter um Nome, um
Exemplo (diagramas, figuras e imagens que o descrevem), um Contexto (a descrio
das situaes sob as quais o padro se aplica), um Problema (uma descrio das foras e
restries envolvidas e como elas interagem) e a Soluo (relacionamentos estticos e
regras dinmicas descrevendo como construir artefatos de acordo com o padro).
Os padres GoF so classificados em 3 tipos: padres de criao (creational),
padres de estrutura (structural) e padres de comportamento (behavioral). No decorrer
deste artigo, sero apresentados exemplos da aplicao destes padres pela arquitetura
do Java EE7.

2. Faade - Estrutural
De acordo com o livro do Gof, o padro Faade busca prover uma nica interface para o
cliente encapsulando um conjunto de interfaces de um ou mais subsistemas. A
motivao para este padro surge em reduzir as complexidades dos subsistemas
envolvidos, minimizando a dependncia e a comunicao entre os subsistemas. Para
atingir este objetivo, inclu-se um objeto faade que prov uma nica interface
simplificada para as operaes mais comuns de um subsistema. O padro de projeto
Faade pode:

Tornar uma biblioteca de software mais fcil de entender e usar;


Tornar o cdigo que utiliza esta biblioteca mais fcil de entender;
Reduzir as dependncias em relao s caractersticas internas de uma biblioteca,
trazendo flexibilidade no desenvolvimento do sistema;
Envolver uma interface mal desenhada, com uma interface melhor definida.

Figura 1 - Esboo do padro Faade

Em aplicaes Java J2EE, imprescindvel quebrar a camada do EJB em duas:


os chamados Entity Beans, que ficam responsveis pelo modelo de dados e pela camada
de persistncia, e os Sessions Beans, que geralmente ficam responsveis pela lgica de
negcios. convencional que clientes acessem Sessions Beans e estes, manipulem os
dados atravs dos Entity Beans, que retornam dados para o cliente.
No entanto, possvel colocar a lgica de negcios nos Entity Beans, mas isto
deve ser evitado, uma vez que no faz sentido que objetos que representam um modelo
de banco de dados, terem operaes e atributos que envolvam outras entidades.
possvel tambm retirar a lgica do Entity Bean e coloc-la no cliente, porm, a
separao de camadas nesse caso desaparece, tornando essa opo problemtica.
Organizar a lgica dentro de vrios Sessions Beans porm traz um overhead na
rede, visto que a cada chamada EJB faz a requisio trafegar na rede at o servidor EJB,
e isto gera atrasos na rede, alm do que, acessar objetos na prpria mquina muito
mais rpido do que fazer requisies pela rede. A soluo ento empacotar um
conjunto de instrues de alto nvel em Sessions Facade, o tornando um local
centralizado de requisies. Deste modo, quando um bean interage com outro no
servidor, ele pode agir localmente fazendo chamadas apropriadas. Este tipo de
abordagem traz ganho de desempenho aplicao, particularmente quando h muitas
chamadas a Beans e Sessions Beans.
Do ponto de vista de percepo, difcil diferenciar um Session Bean de um
Session Faade visto que ambos so Sessions Beans. Porm, um Session Facade pode
implementar um ou vrios casos de uso, enquanto que um Session Bean trata de um
caso de uso ou de uma implementao de um componente. Abaixo segue um diagrama
em UML referente aplicao de um Session Faade no contexto do J2EE:

Figura 2 - Diagrama UML de um Session Bean Faade

3. Proxy - Estrutural
Em programao, o padro de projeto proxy classificado como um padro de projeto
estrutural aplicados a objetos. Sua principal funo fornecer um substituto, ou um
intermediador, entre a classe que quer utilizar o comportamento e a classe que fornece
este comportamento. Abaixo segue um diagrama UML deste tipo de padro:

Figura 3 - Diagrama UML do padro Proxy

Em Java, o padro Proxy muito utilizado no container EJB pelo objeto


javax.ejb.EJBObject que representa uma referncia remota ao EJB. Para o cliente que
utiliza a interface remote de um EJB, a chamada remota ao servidor feita de forma
transparente, facilitando o desenvolvimento de aplicaes distribudas.
Outro exemplo de sua utilizao est no Framework de persistncia Hibernate.
Quando se usa a anotao lazy-loading, tcnica utilizada para acessar o banco de

dados apenas quando necessrio, a chamada a um mtodo como por exemplo,


session.load(id) retorna um proxy. No entanto, a chamada ao banco de dados s feita
quando se acessa alguma propriedade desse objeto, atravs de mtodos getters por
exemplo. Segue abaixo um exemplo do padro Proxy implementado em Java:
public interface IConnection{
public Connection getConnection();
}
public class ConnectionFactory implements IConnection{
public Connection getConnection(){
try {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
return DriverManager.getConnection(
"jdbc:mysql://192.168.1.1/exemplo","root","master");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
public class ConnectionProxy implements IConnection{
private Connection conexao;
public Connection getConnection(){
if (conexao != null){
conexao = new ConnectionFactory().getConnection();
}
return conexao;
}
}
public class teste {
public static void main(String[] args) {
IConnection connection = new ConnectionProxy();
IConnection connection2 = new ConnectionProxy();
connection.getConnection(); //Carrega a conexo do banco
connection.getConnection(); //No necessrio o carregamento
connection2.getConnection(); //Carrega a conexo do banco
connection2.getConnection(); //no necessrio o carregamento
}
}

4. Padro Strategy - Comportamental


O padro de projeto strategy busca definir uma famlia de algoritmos, encapsular cada
um, e torn-los intercambiveis. Este padro permite que algoritmos sejam selecionados
em tempo de execuo e muito utilizado quando se tem muitas estruturas condies e
as desejas eliminar, reduzindo a complexidade do cdigo. Abaixo, segue um diagrama
UML do padro strategy:

Figura 4 - Diagrama UML do padro Strategy

Em Java, um exemplo de aplicao do padro strategy est na implementao da


classe abstrata HttpServlet. Todas as classes que estendem HttpServlet e implementam
os mtodos service(), doGet() e doPost(), recebem como parmetros os objetos
HttpServletRequest, HttpServletResponse, que so passados pelo container (atravs da
injeo de dependncia), que neste caso faz o papel do contexto, em tempo de execuo
quando a classe responde a alguma requisio Http.
Abaixo, segue um exemplo de uma classe controller (mvc) implementada em
Java. Est classe estende HttpServlet e utiliza os objetos HttpServletRequest e
HttpServletResponde para desenvolver suas funes:
@WebServlet("/mvc")
public class ControllerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException
{
String parametro = request.getParameter("logica");
String nomeDaClasse = "br.com.helpdesk.mvc.logica." + parametro;
try {
Class classe = Class.forName(nomeDaClasse);
Logica logica = (Logica) classe.newInstance();
logica.executa(request, response);
}catch (Exception e)
{
throw new ServletException("A lgica de negcios causou uma
exceo", e);
}
}
}

Outro exemplo de implementao do padro strategy no ambiente JEE so os


filtros. Assim como nos Servlets, as classes que implementam a interface Filter,
recebem como parmetros no mtodo doFilter(), os objetos HttpServletRequest e
HttpServletResponse. Segue abaixo um exemplo da implementao do Filter:
public class FiltroConexao implements Filter {
private org.apache.log4j.Logger logger =
Logger.getLogger(FiltroConexao.class.getName());

public FiltroConexao() {}
public void destroy() {}
@SuppressWarnings("static-access")
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
Connection connection = null;
try{
connection =
ConnectionFactoryPool.getInstance().getConnection();
// pendurando a connection na requisio
request.setAttribute("conexao", connection);
chain.doFilter(request, response);
}finally{
try {
if (connection != null){
connection.close();
connection = null;
}
} catch (SQLException e) {
e.printStackTrace();
logger.error(ExceptionToString.faca(e));
}
}
}
public void init(FilterConfig fConfig) throws ServletException {}
}

5. Padro Prototype - Criacional


O padro prottipo utilizado quando a criao de um objeto muito custosa e h um
objeto semelhante j existente para copiar. Portanto, este padro fornece um mecanismo
para copiar o objeto original para um novo objeto e, em seguida, modific-lo de acordo
com as nossas necessidades.
O padro de projeto prottipo determina que o objeto que voc est copiando
deve fornecer o recurso de copiar, ou seja, deve implementar o mtodo clone(). Isto no
deve ser feito por qualquer classe. No entanto, o uso superficial ou profundo das cpias
das propriedades dos objetos depende dos requisitos e da sua deciso de design.
Abaixo segue o diagrama UML referente ao padro prottipo:

Figura 5 - Diagrama UML do padro Prottipo (Prototype)

Suponha, por exemplo, que tenhamos um objeto que ao ser criado carrega dados
do banco de dados. Se precisarmos de vrias instncias desse objeto, no desejvel
que utilizemos o operador new() pois isto ir fazer a aplicao ir ao banco a cada nova
instncia, tornando o custo de criao desse objeto custoso. Como soluo, podemos
implementar o mtodo clone() e ento clonar as propriedades.
Em Java, o mtodo clone implementado pela classe superclasse
Java.lang.Object. Todos os objetos em Java extendem a classe Object, e, portanto,
podem chamar o mtodo clone() atravs do operador super. Abaixo, segue a
implementao do padro prototype em Java, atravs do mtodo clone():
public class Aluno implements Cloneable{
private String nome;
private int matricula;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public int getMatricula() {
return matricula;
}
public void setMatricula(int matricula) {
this.matricula = matricula;
}
@SuppressWarnings("finally")
public Aluno clone() {
Aluno aluno = null;
try {
aluno = (Aluno) super.clone();//Chama o clone de Object.
Isso copia automaticamente todos os atributos.
} catch (CloneNotSupportedException e) {
e.printStackTrace();

}finally{
return aluno;
}
}
}
public class Main {
public static void main(String[] args) {
Aluno aluno = new Aluno();
aluno.setNome("Jos");
aluno.setMatricula(123456);
Aluno aluno2 = (Aluno) aluno.clone();
System.out.println(aluno2.getNome());
}
}

Alm do exemplo acima, diversas classes da arquitetura JEE implementam o


mtodo clone, como por exemplo a classe javax.servlet.http.Cookie:
public class Cookie implements Cloneable {
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e.getMessage());
}
}
}

6. Padro Template Method - Comportamental


O padro Template Method um padro de projeto do tipo comportamental que define
nos mtodos da super classe abstrata, o comportamento fixo da classe, e nas suas
subclasses, a variao do comportamento atravs das implementaes dos mtodos
abstratos da superclasse. Segue abaixo um diagrama UML referente ao padro template
method:

Figura 6 - Diagrama UML do padro Template Method

Em Java, a classe Thread implementa o padro template method atravs do


mtodo abstrato run() que deve ser implementado atravs de todas as classes que
estendem Thread. Segue abaixo um exemplo de uma classe que responsvel por enviar
emails e sobrescreve o mtodo run( ) da classe Thread.
public class EnviaEmail extends Thread {
private String nomeDestinatario;
private String emailDestinatario;
private String assunto;
private String mensagem;
private HashMap<String,String> listaDestinatarios;
public EnviaEmail(String nomeDestinatario, String emailDestinatario,
String assunto, String mensagem) {
this.nomeDestinatario = nomeDestinatario;
this.emailDestinatario = emailDestinatario;
this.assunto = assunto;
this.mensagem = mensagem;
}
public EnviaEmail(HashMap<String, String> listaDestinatarios,
String assunto, String mensagem) {
this.listaDestinatarios = listaDestinatarios;
this.assunto = assunto;
this.mensagem = mensagem;
}
public EnviaEmail(String nomeDestinatario, String emailDestinatario,
HashMap<String, String> listaDestinatariosOcultos,
String assunto, String mensagem) {
this.nomeDestinatario = nomeDestinatario;
this.emailDestinatario = emailDestinatario;
this.listaDestinatarios = listaDestinatariosOcultos;
this.assunto = assunto;
this.mensagem = mensagem;

}
public void despacha() throws EmailException, MalformedURLException {
HtmlEmail email = new HtmlEmail();
email.setCharset("ISO-8859-1");
// Mensagem exibida caso o servidor no suporte HTML
email.setTextMsg("Seu servidor de e-mail no suporta mensagem
HTML");
if ((listaDestinatarios != null) && (emailDestinatario !=
null)){
//Envia e-mail ao tcnico responsvel e tcnicos
administrativos quando um determinado chamado tiver seu
prazo de atendimento vencido
Set<String> listaNomeAdministradores =
listaDestinatarios.keySet();
for (String nomeAdministrador :listaNomeAdministradores){
email.addBcc(listaDestinatarios.get(nomeAdministrad
or), nomeAdministrador);
}
email.addTo(emailDestinatario, nomeDestinatario);
}else if (listaDestinatarios != null){
//Envia e-mail para os tcnicos administrativos, com um
relatrio dos chamados com prazo de atendimento vencidos
Set<String> listaNomeDestinatario =
listaDestinatarios.keySet();
for (String nomeDestinatario: listaNomeDestinatario){
email.addTo(listaDestinatarios.get(nomeDestinatario
),nomeDestinatario);
}
}else{
// Destinatrio
email.addTo(emailDestinatario, nomeDestinatario);
}
// Remetente
email.setFrom(Recurso.getInstance().
getPropriedade("email_sender"),
Recurso.getInstance().getPropriedade("email_name"));
// Assunto
email.setSubject(assunto);
email.setHtmlMsg(mensagem + "<p>&nbsp;</p>");
//Usurio e senha de quem est enviando
email.setAuthenticator(new
DefaultAuthenticator(Recurso.getInstance()
.getPropriedade("email_sender"),
Recurso.getInstance().getPropriedade("email_password")));
//Configuraes do servidor de email
email.setHostName(Recurso.getInstance
().getPropriedade("smtp_server"));
email.setSmtpPort(Integer.parseInt(

Recurso.getInstance().getPropriedade("smtp_port")));
//Envia o email
email.send();
}
@Override
public void run() {
try {
despacha();
}catch (MalformedURLException e) {
e.printStackTrace();
} catch (EmailException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
EnviaEmail enviaEmail = new EnviaEmail();
enviaEmail.start();
}
}

7. Padro Adapter - Estrutural


Em padres de projeto, o padro Adapter converte uma interface de uma classe em
outra interface esperada pelos clientes. Este padro permite a comunicao entre classes
que no poderiam trabalhar juntas devido a incompatibilidade de suas interfaces.
Abaixo segue um diagrama em UML do padro Adapter:

Figura 7 - Diagrama UML do padro Adaptador (Adapter)

Em Java, as classes Wrappers de tipo, como por exemplo, Integer, Double,


Floater, etc. adaptam o tipo primitivo em java.lang.Object.
public class Main {
public static void main(String[] args) {
int x = 5;
Integer numero = new Integer(x);
double y = 5.5;
Double numero2 = new Double(y);
float z = 5.5f;
Float numero3 = new Float(z);
}
}

Outro exemplo de Adapter em Java o mtodo asList() da classe java.util.Array.


Ele recebe um conjunto de strings e retorna um arraylist:
@SafeVarargs
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}

Segue abaixo um exemplo da utilizao do mtodo asList() da classe


java.util.Array:
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> lista = java.util.Arrays.asList("a","b","c","d");
for (String letra : lista){
System.out.println(letra);
}
}
}

8. Factory Method - Criacional


O padro Factory Method define uma interface para criar um objeto mas delega para as
suas subclasse a deciso de que classe instanciar. Muito utilizado quando uma classe
precisa instanciar uma derivao de outra mas no sabe qual. Segue abaixo um
diagrama UML deste padro:

Figura 8 - Diagrama UML do padro Factory Method

Entretanto, existem algumas variaes deste padro em que a classe Fbrica


no possui nenhuma subclasse. Neste caso, a criao dos objetos feita atravs da
disponibilizao de mtodos estticos da classe abstrata. Se a inteno apenas
centralizar a instanciao, recomenda-se a criao de mtodos estticos que retornam os
objetos. Por outro lado, se desejado adiar a criao do objeto para o momento de
execuo, pode-se definir mtodos estticos e redefini-los de acordo com o objeto a ser
criado.
Em Java, a classe java.util.Calendar implementa este ultimo modelo do padro
Factory method nos mtodos getInstance():
public abstract class Calendar implements Serializable, Cloneable,
Comparable<Calendar> {
public static Calendar getInstance()
{
Calendar cal = createCalendar(TimeZone.getDefaultRef(),
Locale.getDefault(Locale.Category.FORMAT));
cal.sharedZone = true;
return cal;
}
public static Calendar getInstance(TimeZone zone)
{
return createCalendar(zone,Locale.getDefault(Locale.Category.FORMAT));
}
public static Calendar getInstance(Locale aLocale)
{
Calendar cal = createCalendar(TimeZone.getDefaultRef(), aLocale);
cal.sharedZone = true;
return cal;
}
public static Calendar getInstance(TimeZone zone, Locale aLocale)
{
return createCalendar(zone, aLocale);
}
}

Segue abaixo um exemplo da utilizao da classe calendar:


public class Main {
public static void main(String[] args) {
Calendar c1 = Calendar.getInstance();
int hora = c1.get(Calendar.HOUR_OF_DAY);
if (hora > 6 && hora < 12) {
System.out.println("Bom Dia");
} else if (hora > 12 && hora < 18) {
System.out.println("Boa Tarde");
} else {

System.out.println("Boa Noite");
}
}
}

Referncias
GAMMA, Erich et al. Design patterns: elements of reusable object-oriented software.
Pearson Education, 1994.
Linha de Cdigo, Design Patterns Fundamentais do J2EE. Disponvel em: <
http://www.linhadecodigo.com.br/artigo/363/design-patterns-fundamentais-doj2ee.aspx> Acesso em 04 de maio de 2014.
Oracle, Core J2EE Patterns - Session Facade. Disponvel em <
http://www.oracle.com/technetwork/java/sessionfacade-141285.html> Acesso em 04 de
maio de 2014.
Devmedia, Conhea o Pattern Proxy - GoF (Gang of Four). Disponvel em <
http://www.devmedia.com.br/conheca-o-pattern-proxy-gof-gang-of-four/4066> Acesso
em 04 de maio de 2014.
Software Design Pattern. In: WIKIPDIA, a enciclopdia livre. Flrida: Wikimedia
Foundation, 2014. Disponvel em:
<http://en.wikipedia.org/wiki/Software_design_pattern>. Acesso em: 27 maio 2014.