Escolar Documentos
Profissional Documentos
Cultura Documentos
2/21
Os padres de projetos h muito tempo foram criados para solucionar problemas que ns,
programadores, encontramos no desenvolvimento de cada dia, aumentando o nvel de modularidade,
a reusabilidade e diminuindo o grau de acoplamento entre os mdulos ou componentes das nossas
aplicaes.
Estes padres (Design Patterns ou simplesmente Patterns) so muito utilizados e conhecidos nas
plataformas Java SE e Java EE. Entretanto, o desenvolvimento de aplicaes mveis na plataforma
Java ME tem amadurecido a cada dia, e BluePrints especficos para a confeco de aplicaes tm
surgido. Tudo isso com o objetivo de diminuir o esforo no desenvolvimento de aplicaes que
precisam ser executadas em dispositivos com caractersticas limitadas, como o caso dos telefones
celulares e Smartphones.
Este artigo ir demonstrar a viabilidade da utilizao de padres de projetos e como estes podem
melhorar significativamente o desenvolvimento de MIDlets (aplicaes para o perfil MIDP). Para
isso, sero apresentados quatro padres de projeto especficos para a plataforma Java ME:
Cascading Menu, Wizard Dialog, Pagination e Slide Show.
3/21
Outros desenvolvedores criaram seus prprios padres e aplicaram em suas aplicaes, relatando
casos de sucesso na utilizao de tais padres. Um deles, chamado Ben Hui, elaborou quatro
padres de projeto: Cascading Menu, Wizard Dialog, Pagination e SlideShow, os quais simplificam o
desenvolvimento de contedo interativo usando o perfil MIDP (Mobile Information Device Profile).
A seguir ser descrito cada padro. Para o desenvolvimento dos exemplos deste artigo, foi utilizada
a IDE Eclipse 3.4 - Ganymede (www.eclipse.org/ganymede/) juntamente com o plugin EclipseME
1.7.9 (http://eclipseme.org/) e para a emulao, a ferramenta Sun Java Wireless Toolkit 2.5.2 for
CLDC, para as especificaes CLDC 1.1 e MIDP 2.0. Os exemplos de cdigo dos padres de
projetos mostrados neste artigo foram baseados nas implementaes do autor dos padres. O link
para baix-los est disponvel na seo Links. Para cada padro de projeto apresentado, ser
utilizado um quadro que mostra a arquitetura e descreve sucintamente o objetivo, o problema e sua
soluo, os elementos que fazem parte do padro, a conseqncia da aplicao deste pattern e sua
implementao.
4/21
5/21
juntamente com seu mtodo commandAction(), e configurar o mtodo setCommandListener() do
objeto que gerou o evento. No desenvolvimento de MIDlets comuns, cada objeto List implementa
implicitamente (por meio da constante List.IMPLICIT passada no construtor da classe List) a interface
javax.microedition.CommandListener. Sendo assim, o papel do controlador realizado por esta para
gerenciar o fluxo da aplicao e redirecionar para o menu de acordo com a escolha do usurio. Essa
abordagem s vivel quando a aplicao estiver usando poucas subclasses de List para representar
as listas com itens de menus. Supondo que uma MIDlet simples em Java ME tivesse mais de 15
menus, alm de ser necessrio criar subclasses de List para cada menu, a gerncia do controle do
fluxo entre os menus torna-se mais complexo e custoso.
Uma implementao de estrutura semelhante a essa pode ser alcanada por meio do padro de
projeto MVC (Model-View-Controller/Modelo-Viso-Controlador). Neste padro, ocorre o total
desacoplamento das responsabilidades de cada parte da aplicao, sendo que o Modelo de dados
responsvel pela representao das regras de negcio, a Viso renderiza o modelo de dados por
meio de componentes de Interface Grfica com o Usurio (GUI Graphical User Interface, na
verdade, em Java ME este termo pode ser substitudo por LCDUI Liquid Crystal Display User
Interface que so componentes grficos de MIDP que foram projetados especificamente para
serem visualizados por dispositivos com telas reduzidas) e o Controlador responsvel por capturar
eventos gerados pelo usurio (que pode ser o clique de uma tecla de um dispositivo), gerenciar o
fluxo da aplicao e controlar a conversa com o modelo e a viso. O modelo informa viso que
os dados foram alterados e esta renderiza os dados com os valores atualizados. A arquitetura MVC
mostrada na Figura 2.
O padro Cascading Menu (ver Figura 3) pode ser considerado uma verso mvel do MVC.
Sendo assim, o modelo de dados pode ser mantido e atualizado independente do tipo de viso que
ser utilizada. Qualquer rearranjo no sistema de menus implicar apenas na reorganizao da
estrutura do modelo representada por uma rvore de menus.
6/21
Figura 3. Arquitetura do padro Cascading Menu.
Objetivo
Lojas
Lojas
Restaurantes
Lazer
Automveis
Livros
Moda
Restaurantes
Padarias
Cafs
Refeies
Lazer
Museus
Galerias
Espetculos
O componente MenuElement representa o modelo, que ser utilizado para criar a rvore de menus.
Cada MenuElement representa um n (ou item do menu) da rvore de menus. Esses ns podem se
7/21
comportar tanto como um n-pai ou n-filho. Analisando a Listagem 2, podemos perceber que a
relao de hierarquia realizada pelo mtodo addChild() que foi sobrecarregado e possui suas
verses recebendo ambos dois parmetros: addChild(child,next_container), no qual child representa o
item de menu que est sendo adicionado e next_container, o prximo MenuElement a ser exibido
assim que o item do menu for selecionado (se selecionssemos o item de menu Lojas na tela do
menu principal, a tela de lojas disponveis seria exibida em seguida); e addChild(child,display) onde
display ser o Displayable que ser mostrado assim que child for selecionado. Esta classe possui o
vetor children representando um container para MenuElements e o Hashtable menuMap, que far o
mapeamento dos prximos itens de menu ou Displayables que sero exibidos. O mtodo
commandAction() possui a regra de negcio para escolher o que ser visualizado assim que o item de
menu for selecionado. Assim que o modelo criado, a classe MenuList, que uma especializao de
uma List, renderiza os dados representados pelo modelo, realizando dessa forma o papel da camada
de viso. A grande vantagem que MenuList pode ser reutilizada em aplicaes futuras, uma vez que
a viso est totalmente desacoplada do modelo.
A Listagem 3 representa este componente. O mtodo showMenu() de MenuList o responsvel por
visualizar os dados do modelo. Ele possui um lao interno responsvel por recuperar todos os
MenuElements salvos em children e visualiz-los. Mas primeiro ele chama o mtodo deleteAll(),
sobrescrito de List, para remover quaisquer itens de menu que estejam sendo exibidos no momento.
Porm, para que os dados possam ser exibidos assim que a navegao pelos menus terminar, as
classes obrigatoriamente devem ser um Displayable.
A Listagem 4 mostra a implementao de SampleMenuAction, que ser a classe que visualizar os
dados retornados. No nosso exemplo, adotamos um carter mais didtico no qual o dado visualizado
ser somente o nome do item de menu que o usurio selecionou. Porm, em uma aplicao mvel
comercial, os dados poderiam ser resultado de uma pesquisa em um banco de dados armazenado em
um servidor remoto ou da consulta utilizando um Web Service. A classe SampleMenuAction estende
TextBox, que o componente de MIDP que permite entrada de textos longos, ocupando toda a tela
do dispositivo. Basicamente, ela define seu construtor que chama o construtor de TextBox e so
passados os parmetros, respectivamente, representando o ttulo, o texto, a quantidade mxima de
caracteres e a restrio de entrada de texto, indicando que qualquer texto alfanumrico e com
caracteres especiais pode ser inserido. Alm disso, ela implementa a interface MDisplayable
(Listagem 5) e o mtodo onDisplay(), que chamado quando o usurio seleciona a opo de menu
associada a um MDisplayable.
A Listagem 6 descreve a MIDlet que utiliza os outros componentes participantes do padro
Cascading Menu. Essencialmente, os MenuElements so instanciados e o mtodo addChild() de cada
objeto chamado e configurado para poder construir a hierarquia de menus. Por fim, o mtodo
showMenu() de MenuList chamado e passado como parmetro o objeto que representa o menu
principal (varivel main).
8/21
no mtodo addDialog()) e startWizard() que, respectivamente, adiciona os dilogos no vetor e
retorna o ndice da tela de dilogo que est sendo adicionada.
Inicialmente, a classe WDialog que uma especializao de javax.microedition.lcdui.Form
declara vrias flags que representam as aes de navegao (NEXT e BACK), a direo do fluxo da
aplicao: avanando (FORWARD) ou retornando para a tela anterior (BACKWARD); e valores para
serem retornados de acordo com a validao dos dados, se estes foram aceitos (OK) a prxima tela
ser mostrada, caso contrrio (REJECT) a mudana de tela no acontecer enquanto os dados
passados no forem vlidos.
Continuando, o mtodo initByEngine() chama o mtodo abstrato initDialog() que o responsvel
por inicializar todas as telas de dilogos, permitindo configurar os objetos grficos (como
Commands, TextFields, ChoiceGroups, etc.) logo na inicializao de uma WDialog (subclasses desta).
Ele deve ser implementado por todas as subclasses de WDialog (no nosso exemplo, WPage1,
WPage2, WPage3 e WPage4). Esta classe possui tambm o mtodo onLeave() que realiza a
validao dos dados assim que o fluxo da aplicao estiver entrando em uma tela; e o mtodo
onEnter() que, analogamente a onLeave() tambm realiza a validao dos dados, porm, quando
uma tela (representada por subclasses de WDialog) estiver prestes a ser exibida.
A MIDlet que exemplifica este padro permite pesquisarmos informaes de cidades de acordo
com algum critrio de busca. A aplicao possui quatro telas simples, que so representadas pelos
componente WPage1 (Listagem 9), WPage2 (Listagem 10), WPage3 (Listagem 11) e WPage4
(Listagem 12).
A primeira tela mostra apenas uma informao inicial indicando como o usurio deve prosseguir
para a execuo da MIDlet. A segunda mostra uma lista de cidades disponveis para escolha
(representada pelo componente ChoiceGroup). A terceira permite que um termo de busca seja
informado de acordo com o filtro (a cidade) selecionado anteriormente. Caso este termo no seja
informado, a engine trata de validar os dados por meio do mtodo sobrescrito onLeave() e exibe uma
mensagem informando que o campo de pesquisa deve ser preenchido com no mnimo 3 caracteres,
no permitindo que o fluxo da aplicao mude para outra tela enquanto o campo de busca no for
preenchido. Caso a validao ocorra com sucesso, a quarta tela ser exibida. No nosso exemplo,
para melhor entendimento, ela apenas ir mostrar o nome da cidade selecionada (Wizardlet.answer1)
e o valor que foi informado no campo de pesquisa (Wizardlet.answer2). A Listagem 13 mostra a
MIDlet utilizando os outros componentes do padro, na qual o mtodo addDialog() chamado e
passados como parmetros os objetos das subclasses de WDialog. Ao trmino, chamado o mtodo
startWizard() para iniciar a exibio das telas da aplicao.
9/21
Objetivo
Padro Pagination
Devido aos dispositivos mveis possurem uma tela limitada, a disposio dos objetos de texto
reduzida a aproximadamente 10 linhas (dependendo do tamanho da tela do dispositivo), dificultando
a navegao, visualizao e legibilidade do contedo. Devido a esta limitao, torna-se necessrio o
uso de mtodos que paginem o texto, seja por barra de rolagem ou por menus: avanar e voltar. O
padro Pagination visa contornar este problema por meio da utilizao do componente PagableList.
Este padro permite que uma lista de elementos seja dividida em pginas menores para melhorar a
visibilidade e navegabilidade dos dados apresentados, sendo utilizado para isso outro padro de
projeto, chamado Proxy, que utilizado quando devem existir vrias cpias de um objeto complexo,
porm s vezes o processo de cpia pode requerer um espao significativo na memria, o que
conseqentemente causa uma perda no desempenho da aplicao. Nessa ocasio, outro objeto
(proxy) instanciado em vez de ocorrer diretamente a instanciao do objeto real. Para minimizar o
carregamento dos dados, o padro utiliza outro padro, chamado de Flyweight. Ele fundamental
10/21
no padro Pagination, pois, h muitos objetos (os itens da lista) e estes precisam ser carregados de
forma a no ocupar muita memria durante este processamento. Sendo assim, este processo deve
ocorrer por demanda, ou seja, somente quando necessrio. Na Figura 6 vemos a arquitetura do
padro Pagination.
Para exemplificar a facilidade na seleo e leitura dos itens na lista, realizado um comparativo de
como uma mesma aplicao executada no emulador sem (Figura 7) ou com (Figura 8) a
utilizao deste padro. Na Figura 7, percebemos claramente um inchao visual na MIDlet. Caso
o usurio necessite acessar, por exemplo, o item na posio 45 de uma lista de 50 itens, preciso
que o mesmo navegue incessantemente pelos elementos at alcanar o item desejado. J na Figura
8, vemos uma MIDlet mais enxuta, com menos itens por pgina, sendo possvel avanar na
paginao, representado pelo comando More, ou recuar, se selecionarmos o comando Prev.
Na Listagem 14, percebemos que a classe PagableList possui mtodos chamados showPrevPage() e
showNextPage(). Estes mtodos so centrais no padro Pagination, pois acionam respectivamente a
pgina anterior e posterior, facilitando sua navegabilidade e proporcionando maior conforto visual ao
usurio, haja vista que no sero exibidas telas carregadas de textos (mais de 20 itens, por exemplo)
ou figuras, o que normalmente necessita de uma parte considervel de memria do dispositivo para
que a lista seja renderizada. Alm disso, temos o mtodo utilitrio updateList(), que atualiza os itens
da lista e os mtodos sobrescritos da classe List (existem outros mtodos de List que foram
sobrescritos, entretanto, foram omitidos na listagem por questes de espao), que so append(),
delete(), insert() que respectivamente adiciona cada texto do item e sua imagem (opcional) nos
vetores que os representam (allStrings e allImages), deleta e insere o texto ou imagem do item da
lista nos vetores de acordo com sua posio. Na Listagem 15, a MIDlet representando este padro,
inicialmente instancia um objeto PagableList. Depois, dentro do mtodo startApp(), o lao adiciona
um nmero significativo de itens no objeto (100 itens) PagableList para colocar o padro Pagination
em funcionamento.
Pattern: Pagination
Objetivo
11/21
Implementao
12/21
13/21
Objetivo
Frameworks em Java ME
A utilizao massiva de padres de projetos na plataforma Java ME tem proporcionado o
desenvolvimento de frameworks (alguns open sources e outros comerciais) que permitem criar
aplicaes mveis mais complexas e robustas. Alguns exemplos so o Floggy (www.floggy.org)
projeto verde e amarelo que implementa a idia de persistncia no modelo objeto-relacional e o
J2ME Polish (www.j2mepolish.org), que alm de ser um framework que incrementa vrios aspectos
em Java ME, como novos widgets, servios de log, serializao de objetos, desenvolvimento de
GUIs baseadas em CSS (Cascading Style Sheet) e outros, possui integrao com IDEs conhecidas,
como o Eclipse, Netbeans, IntelliJ e permite, por meio de diretivas de pr-processamento, que uma
nica aplicao seja desenvolvida para vrias famlias de dispositivos, diminuindo com isso o
problema da fragmentao. Este framework possui uma verso livre, mais restrita em
funcionalidades, e outra verso comercial que possui todas as novidades disponveis no framework.
14/21
Percebemos que apesar do desenvolvimento de framework em Java ME ser restrito, devido
plataforma ainda no suportar recursos mais complexos como reflexo (tambm chamado de
introspeco), vrias empresas e pesquisadores vm criando frameworks que abrangem diversos
domnios, a exemplo os frameworks Floggy e J2ME Polish citados anteriormente (recomendo o
leitor a realizar uma pesquisa em sites de hospedagens de projetos Open Source, como
SourceForge.net, Google Code, etc. para analisar a quantidade significativa de frameworks
desenvolvidos para Java ME).
Ns desenvolvedores esperamos ansiosamente por novas JSRs para as verses da configurao
CLDC 1.1 e perfil MIDP 2.0 ou um incremento da verso mvel de Java (a to aguardada MIDP
3.0) que suporte tais recursos citados anteriormente, o que conseqentemente iria tornar a
plataforma uma das mais promissoras para desenvolvimento de aplicaes comerciais mveis.
Concluses
Este artigo mostrou a viabilidade de se aplicar padres de projetos em aplicaes mveis para Java
ME, sendo descritos, por meio de exemplos prticos, quatro padres: Cascading Menu, Wizard
Dialog, Pagination e Slide Show, que solucionam problemas comumente enfrentados por ns
durante a composio de GUIs para dispositivos MIDP.
A criao de um padro de projeto, na maioria das vezes, implica na utilizao de duas ou mais
classes abstratas e interfaces. Por isso, caso a aplicao utilize muitos padres de projeto, a
conseqncia disso pode ser uma MIDlet pesada e lenta, o que acabaria diminuindo o desempenho
do dispositivo. Entretanto, isso no significa que a utilizao de mais de um padro de projeto se
torne invivel para as aplicaes (por exemplo, a MIDlet Suite com os quatro padres de projetos
que foram utilizados neste artigo ficou com um tamanho aproximado de 12 Kb sem utilizar um
obfuscador). Nesse caso, determinado padro pode sofrer uma leve adaptao para se comportar
bem ao ambiente mvel, porm sem perder as suas caractersticas. At o prximo artigo!
Ramon Ribeiro Rabello (ramon.rabello@gmail.com) desenvolvedor Java h 4 anos, tendo experincia nas trs
especificaes:JSE, JEE e JME. J trabalhou em projetos de aplicaes mveis e servios M-Payment. Publicou artigos sobre
plataformas mveis e atualmente cursa Mestrado pela Universidade Federal de Pernambuco (UFPE) em Engenharia de Software.
Pedro J. F. Treccani (pedrotreccani@gmail.com) desenvolvedor Java h 4 anos, com experincia nas trs especificaes de
Java. J trabalhou no desenvolvimento de projetos integrando aplicaes mveis com Sistemas Integrados de Gesto
Empresarial(SIGE),servios M-Commerce e E-Commerce. Publicou artigos sobre plataformas mveis, cursando atualmente
Mestrado como aluno especial pela Universidade Federal de Par (UFPA) em Engenharia de Software.
15/21
Thienne Johnson (thienne@ieee.org) professora da Unama, com mestrado (UFSCar) e Doutorado (UFPE) em Cincia da
Computao. Atualmente faz ps-doutorado na Faculdade de Engenharia Eltrica e de Computao na Unicamp. autora do livro
Java para Dispositivos Mveis Desenvolvendo Aplicaes com J2ME, da editora Novatec.
Links
javaworld.com/javaworld/jw-12-2002/jw-1213-j2medesign.html
Sobre os quatro padres de projetos.
eclipse.org/ganymede
Site da IDE Eclipse Ganymede.
eclipseme.org
Site do EclipseME.
http://www.ibm.com/developerworks/library/wi-arch22/
O Padro de Projeto Factory em MIDP 2.0.
Listagem 2. Implementao do componente MenuElement: MenuElement.java
public class MenuElement implements CommandListener {
public Vector children = new Vector();
Hashtable menuMap = new Hashtable();
public String text;
// construtor e outros mtodos utilitrios
// adiciona um item de menu e liga ao prximo container
public void addChild(MenuElement child, MenuElement next_container) {
children.addElement(child);
menuMap.put(child, next_container);
}
// adiciona um item de menu e liga ao prximo componente grfico
public void addChild(MenuElement child, Displayable display) {
children.addElement(child);
menuMap.put(child, display);
}
public void commandAction(Command command, Displayable displayable) {
if (command.equals(List.SELECT_COMMAND) && displayable instanceof MenuList){
MenuList list = (MenuList) displayable;
int i = list.getSelectedIndex();
MenuElement item = (MenuElement) children.elementAt(i);
Object next = menuMap.get(item);
if (next instanceof MenuElement)
list.showMenu((MenuElement) next);
else if (next instanceof MDisplayable && next instanceof Displayable) {
((MDisplayable) next).onDisplay(item);
list.getDisplay().setCurrent((Displayable) next);
}
else if (next instanceof Displayable)
list.getDisplay().setCurrent((Displayable) next);
}
}
}
16/21
this.setTitle(menu.text);
setCommandListener(menu);
}
}
17/21
WDialog prev_dialog = (WDialog) dialogs.elementAt(i1 - 1);
if (cur_dialog.onLeave(WDialog.BACKWARD) != WDialog.OK) return;
if (prev_dialog.onEnter(WDialog.BACKWARD) != WDialog.OK) return;
display.setCurrent(prev_dialog);
}
}
}
}
18/21
}
}
else return OK;
}
}
19/21
int maxItem = 4; // s um default
int curItem = 0;
CommandListener listener = null;
public PagableList(String title, int listType) {
super(title, listType);
addCommand(MORE_COMMAND);
addCommand(PREV_COMMAND);
super.setCommandListener(new CommandAction());
}
public PagableList(String title, int listType, String[] stringElements,
Image[] imageElements)
{
super(title, listType);
addCommand(MORE_COMMAND);
addCommand(PREV_COMMAND);
super.setCommandListener(new CommandAction());
}
private void updateList() {
int s = super.size();
for (int i = 0; i < s; i++) {
super.delete(0);
}
for (int i = curItem; i < curItem + maxItem; i++) {
// se i exceder o ltimo ndice de allStrings, ento sai do lao
if (!(i < allStrings.size()))
break;
String a_item = (String) allStrings.elementAt(i);
Image img = null;
Object obj = allImages.elementAt(i);
if (obj == DUMMY)
img = null;
else img = (Image) obj;
super.append(a_item, img);
}
}
public void showPrevPage() {
int last = allStrings.size() - 1;
if (curItem - maxItem >= 0) {
curItem -= maxItem;
updateList();
}
}
public void showNextPage() {
int last = allStrings.size() - 1;
if (curItem + maxItem <= last) {
curItem += maxItem;
updateList();
}
}
public int append(String stringPart, Image imagePart) {
if (stringPart == null) throw new NullPointerException();
if (imagePart != null && imagePart.isMutable()) throw new IllegalArgumentException();
allStrings.addElement(stringPart);
if (imagePart != null)
allImages.addElement(imagePart);
else allImages.addElement(DUMMY);
int last = allStrings.size() - 1;
if (last < curItem + maxItem) super.append(stringPart, imagePart);
return last;
}
public void delete(int elementNum) throws IndexOutOfBoundsException {
if (elementNum >= allStrings.size()) throw new IndexOutOfBoundsException();
allStrings.removeElementAt(elementNum);
allImages.removeElementAt(elementNum);
// if affected element is currently showing, then refresh the list
if (elementNum >= curItem && elementNum < curItem + maxItem) updateList();
20/21
}
public void insert(int elementNum, String stringPart, Image imagePart) {
if (elementNum >= allStrings.size()) throw new IndexOutOfBoundsException();
if (stringPart == null) throw new NullPointerException();
if (imagePart != null && imagePart.isMutable()) throw new IllegalArgumentException();
allStrings.insertElementAt(stringPart, elementNum);
if (imagePart != null)
allImages.insertElementAt(imagePart, elementNum);
else
allImages.insertElementAt(DUMMY, elementNum);
if (elementNum >= curItem && elementNum < curItem + maxItem)
updateList();
}
private class CommandAction implements CommandListener {
public void commandAction(Command command, Displayable displayable) {
if (command == MORE_COMMAND)
showNextPage();
else if (command == PREV_COMMAND)
showPrevPage();
else if (listener != null)
listener.commandAction(command, displayable);
}
}
}
Listagem 16. Classe que configura os slides e durao das transies: SlideEngine.java
public class SlideEngine {
Display display;
Vector sequence; // Conter a seqncia de slides
Thread thread;
Timer timer;
public SlideEngine(Display d) {
display = d;
sequence = new Vector();
}
public void addSlide(Displayable slide, int t) {
sequence.addElement(slide);
sequence.addElement(new Integer(t));
}
public void startShow() {
timer = new Timer();
thread = new Thread(timer);
thread.start();
}
public void endShow() {
timer.done = true;
}
class Timer implements Runnable {
int time;
boolean done;
public void run() {
done = false;
int cur = 0; // ndice da seqncia
while (!done && cur < sequence.size()) {
21/21
Object o = sequence.elementAt(cur);
System.out.println("sequence: " + o);
if (o instanceof Displayable) {
Displayable d = (Displayable) o;
display.setCurrent(d);
}
else if (o instanceof Integer) {
time = ((Integer) o).intValue();
try {
Thread.sleep(time);
}
catch (Exception e) {}
}
cur++; // avana para o prximo slide
}
}
}
}