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