por Rodrigo Rebouças de Almeida
Figura 1: Aplicação sendo acessada por várias interfaces
import java.awt.Button; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.awt.Frame; public class TelaVotacao extends Frame implements ActionListener { private TelaResultado telaResult; private TelaResultadoPercentual telaResultPerc; private Map <String,Integer>opcoes; private ArrayList <String>listaOpcoes; // para obter as opções em ordem public TelaVotacao() { super("Tela de Votação - Enquete"); telaResult = new TelaResultado(this); telaResult.setLocation(120, 5); // posicao na tela telaResultPerc = new TelaResultadoPercentual(this); telaResultPerc.setLocation(250, 5); // posicao na tela listaOpcoes = new ArrayList<String>(); this.opcoes = new HashMap<String, Integer>(); this.adicionaOpcao("Opção 1"); this.adicionaOpcao("Opção 2"); this.adicionaOpcao("Opção 3"); this.adicionaOpcao("Opção 4"); criarBotoes(); telaResult.inicializar(listaOpcoes); telaResultPerc.inicializar(listaOpcoes); this.setSize(100, 120); this.setLayout(new GridLayout(0, 1)); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { e.getWindow().hide(); System.exit(0); } }); this.show(); telaResult.show(); telaResultPerc.show(); } /** * Adiciona uma opcao à enquete **/ private void adicionaOpcao(String opcao) { listaOpcoes.add(opcao); this.opcoes.put(opcao, new Integer(0)); } /** * Cria os botoes da tela de votos **/ public void criarBotoes() { Button botao; for (String opcao : listaOpcoes) { botao = new Button(opcao); botao.setActionCommand(opcao); botao.addActionListener(this); this.add(botao); } } /** * Método executado ao clicar nos botões */ public void actionPerformed(ActionEvent event) { String opcao = event.getActionCommand(); this.votar(opcao); // incrementando o voto // Atualizando a tela de resultados absolutos telaResult.novoVoto(opcao, getVotos(opcao)); // Atualizando a tela de resultados percentuais telaResultPerc.novoVoto(opcao, getVotos(opcao), getTotalVotos()); } /** * Incrementa o voto da opção entrada */ public void votar(String opcao) { int votoAtual = ((Integer) this.opcoes.get(opcao)).intValue(); this.opcoes.put(opcao, new Integer(++votoAtual)); } /** * Retorna a soma dos votos de todas as opções da enquete * @return int soma dos votos de todas as opções da enquete */ public int getTotalVotos() { int total = 0; for (Integer votos : opcoes.values()) { total += votos.intValue(); } return total; } /** * Retorna a quantidade de votos de uma opção individual */ public int getVotos(String opcao) { return ((Integer) this.opcoes.get(opcao)).intValue(); } }
import java.awt.GridLayout; import java.awt.Label; import java.awt.Window; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.awt.Frame; public class TelaResultado extends Window{ private Map <String, Label>labels = new HashMap(); public TelaResultado(Frame parent){ super(parent); this.setSize(110,120); this.setLayout(new GridLayout(0,2)); // Grid com qualquer numero // de linhas e duas colunas this.add(new Label("Votos")); this.add(new Label()); } /** * Recebe a lista de opcoes inicial */ public void inicializar(ArrayList <String> opcoes) { Label label; Label votos; for(String opcao : opcoes){ if(!labels.containsKey(opcao)){ label = new Label(opcao+" - "); votos = new Label(""+0); labels.put(opcao,votos); this.add(label); this.add(votos); } } } /** * Atualiza a quantidade de votos para uma determinada opcao */ public void novoVoto(String opcao, int nvotos) { Label votos; votos = labels.get(opcao); votos.setText(""+nvotos); } }
Figura 2: Fluxo de eventos e informações em uma arquitetura MVC
import java.util.HashMap; import java.util.Map; import java.util.Set; public class EnqueteSimples { private Map <String,Integer>opcoes; public EnqueteSimples(){ opcoes = new HashMap<String, Integer>(); } /** * Adiciona uma opção para ser votada na enquete * @param opcao nome da opção */ public void addOpcao(String opcao){ opcoes.put(opcao,new Integer(0)); } /** * Retorna um iterador de opções disponíveis na enquete * @return Iterator opções disponiveis na enquete */ public Set <String> getOpcoes(){ return opcoes.keySet(); } /** * Incrementa um voto para opção * @param opcao opção que receberá voto */ public void votar(String opcao){ int votoAtual = ((Integer)opcoes.get(opcao)).intValue(); opcoes.put(opcao,new Integer(++votoAtual)); } /** * Retorna a soma dos votos de todas as opções da enquete * @return int soma dos votos de todas as opções da enquete */ public int getTotalVotos(){ int total = 0; for(Integer votos : opcoes.values()){ total+= votos.intValue(); } return total; } /** * Retorna a quantidade de votos de uma opção individual * @param opcao opção que se quer o voto * @return int quantidade de votos da opção */ public int getVotos(String opcao){ return (opcoes.get(opcao)).intValue(); } }
Figura 3: Modelo implementando padrão Observer
import java.util.List; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Set; public class EnqueteSimples { private Map <String,Integer>opcoes; private List <EnqueteListener>enqueteListeners = new LinkedList(); public EnqueteSimples(){ opcoes = new HashMap<String, Integer>(); } /** * Adiciona uma opção para ser votada na enquete * @param opcao nome da opção */ public void addOpcao(String opcao){ opcoes.put(opcao,new Integer(0)); this.disparaNovaOpcao(opcao); } /** * Retorna um iterador de opções disponíveis na enquete * @return Iterator opções disponiveis na enquete */ public Set <String> getOpcoes(){ return opcoes.keySet(); } /** * Incrementa um voto para opção * @param opcao opção que receberá voto */ public void votar(String opcao){ int votoAtual = (opcoes.get(opcao)).intValue(); opcoes.put(opcao,new Integer(++votoAtual)); this.disparaNovoVoto(opcao); } /** * Retorna a soma dos votos de todas as opções da enquete * @return int soma dos votos de todas as opções da enquete */ public int getTotalVotos(){ int total = 0; for(Integer votos : opcoes.values()){ total+= votos.intValue(); } return total; } /** * Retorna a quantidade de votos de uma opção individual * @param opcao opção que se quer o voto * @return int quantidade de votos da opção */ public int getVotos(String opcao){ return (opcoes.get(opcao)).intValue(); } /** * Adiciona um EnqueteListener, um objeto interessado em * receber eventos lançados pela Enquete * @see EnqueteListener * @param listener objeto interessado em receber eventos */ public synchronized void addEnqueteListener(EnqueteListener listener){ if(enqueteListeners.contains(listener)){ return; } this.enqueteListeners.add(listener); } /** * Informa aos objetos interessados nos eventos lançados * pela Enquete que um novo voto foi contabilizado. */ private synchronized void disparaNovoVoto(String opcao){ for(EnqueteListener listeners : this.enqueteListeners){ listeners.novoVoto(new EnqueteEvent(this,opcao)); } } /** * Informa aos objetos interessados nos enventos lançados * pela Enquete que uma nova opção foi adicionada. */ private synchronized void disparaNovaOpcao(String opcao){ for(EnqueteListener listeners : this.enqueteListeners){ listeners.novaOpcao(new EnqueteEvent(this,opcao)); } } }
import java.util.EventObject; public class EnqueteEvent extends EventObject { private String opcao = null; private int votos = 0; public EnqueteEvent(EnqueteSimples source){ super(source); } public EnqueteEvent(EnqueteSimples source,String opcao){ this(source); this.opcao = opcao; } /** * Retorna a opção associada ao evento gerado. * A opção pode ser uma nova opção adicionada à EnqueteSimples * ou a opção escolhida para adicionar um novo voto. * @return String opção */ public String getOpcao() { return opcao; } /** * Retorna o numero de votos da opcao * @return int votos */ public int getVotos() { return ((EnqueteSimples)this.source).getVotos(opcao); } /** * Retorna o total de votos da enquete * @return int */ public int getTotalVotos() { return ((EnqueteSimples)this.source).getTotalVotos(); } }
import java.util.EventListener; public interface EnqueteListener extends EventListener { /** * Invocado quando um novo voto é contabilizado na Enquete. * @param event Evento gerado pela Enquete. */ public void novoVoto(EnqueteEvent event); /** * Invocado quando uma nova opção é adicionada à Enquete. * @param event Evento gerado pela Enquete. */ public void novaOpcao(EnqueteEvent event); }
import java.awt.GridLayout; import java.awt.Label; import java.awt.Window; import java.util.HashMap; import java.util.Map; import java.awt.Frame; public class TelaResultado extends Window implements EnqueteListener{ private Map <String, Label>labels = new HashMap(); public TelaResultado(Frame parent){ super(parent); this.setSize(110,120); this.setLayout(new GridLayout(0,2)); // Grid com qualquer numero // de linhas e uma coluna this.add(new Label("Votos")); this.add(new Label()); } /** * @see enquete.model.EnqueteListener#novaOpcao(EnqueteEvent) */ public void novaOpcao(EnqueteEvent event) { String opcao = event.getOpcao(); Label label; Label votos; if(!labels.containsKey(opcao)){ label = new Label(opcao+" - "); votos = new Label(""+event.getVotos()); labels.put(opcao,votos); this.add(label); this.add(votos); } } /** * @see enquete.model.EnqueteListener#novoVoto(EnqueteEvent) */ public void novoVoto(EnqueteEvent event) { String opcao = event.getOpcao(); Label votos; votos = labels.get(opcao); votos.setText(""+event.getVotos()); } }
import java.awt.GridLayout; import java.awt.Label; import java.awt.Window; import java.util.HashMap; import java.util.Map; import java.awt.Frame; public class TelaResultadoPercentual extends Window implements EnqueteListener{ private Map <String,Label>labels = new HashMap(); public TelaResultadoPercentual(Frame parent){ super(parent); this.setSize(180,120); this.setLayout(new GridLayout(0,2)); // Grid com qualquer numero // de linhas e uma coluna this.add(new Label("Percentual")); this.add(new Label()); } /** * @see enquete.model.EnqueteListener#novaOpcao(EnqueteEvent) */ public void novaOpcao(EnqueteEvent event) { String opcao = event.getOpcao(); Label label; Label votos; if(!labels.containsKey(opcao)){ label = new Label(opcao+" - "); votos = new Label(""+event.getVotos()+" %"); labels.put(opcao,votos); this.add(label); this.add(votos); } } /** * @see enquete.model.EnqueteListener#novoVoto(EnqueteEvent) */ public void novoVoto(EnqueteEvent event) { String opcao = event.getOpcao(); Label votos; votos = labels.get(opcao); votos.setText(""+(event.getVotos()*100/event.getTotalVotos())+" %"); } }
import java.awt.Button; import java.awt.GridLayout; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.Collection; import java.awt.Frame; public class TelaVotacao extends Frame implements EnqueteListener{ private Collection <String>botoes = new ArrayList(); private ActionListener controller; public TelaVotacao(ActionListener controller){ super("Tela de Votação - Enquete"); this.setSize(100,120); this.setLayout(new GridLayout(0,1)); // Grid com qualquer numero // de linhas e uma coluna this.controller = controller; this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { e.getWindow().hide(); System.exit(0); } }); } /** * @see enquete.model.EnqueteListener#novaOpcao(EnqueteEvent) */ public void novaOpcao(EnqueteEvent event) { String opcao = event.getOpcao(); Button botao; if(!botoes.contains(opcao)){ botoes.add(opcao); botao = new Button(opcao); botao.setActionCommand(opcao); botao.addActionListener(controller); this.add(botao); } } /** * @see enquete.model.EnqueteListener#novoVoto(EnqueteEvent) */ public void novoVoto(EnqueteEvent event) { // Nothing to do } }
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TelaVotacaoCtrl implements ActionListener{ private EnqueteSimples enquete; public TelaVotacaoCtrl(EnqueteSimples enquete){ this.enquete = enquete; } /** * Evento lançado pelo clique nos botoes da TelaVotacao * @see java.awt.event.ActionListener#actionPerformed(ActionEvent) */ public void actionPerformed(ActionEvent event) { enquete.votar(event.getActionCommand()); } }
public class Enquete{ public static void main(String[] args) { // Modelo EnqueteSimples enquete= new EnqueteSimples(); // Controlador da Interface "TelaVotacao" TelaVotacaoCtrl ctrl = new TelaVotacaoCtrl(enquete); // Interface que altera o estado do modelo TelaVotacao votacao = new TelaVotacao(ctrl); votacao.setLocation(5,5); // Interface que exibe o resultado absoluto da votacao TelaResultado resultado = new TelaResultado(votacao); resultado.setLocation(120,5); // Interface que exibe o resultado percentual da votacao TelaResultadoPercentual resultadoPerc = new TelaResultadoPercentual(votacao); resultadoPerc.setLocation(250,5); // Adicionando as interfaces interessadas na mudança do // estado do modelo enquete.addEnqueteListener(votacao); enquete.addEnqueteListener(resultado); enquete.addEnqueteListener(resultadoPerc); // Povoando o modelo enquete.addOpcao("Opção 1"); enquete.addOpcao("Opção 2"); enquete.addOpcao("Opção 3"); enquete.addOpcao("Opção 4"); // Exibindo as interfaces votacao.show(); resultado.show(); resultadoPerc.show(); } }
Clique aqui para fazer o download do código fonte desta aula
MVC programa