Jump to content

Archived

This topic is now archived and is closed to further replies.

Pedro Muyala

Atributos de uma classe em HASHMAP?

Recommended Posts

Olá, estou com uma nova dúvida, agora na modelagem: Na verdade, os nomes dos atributos do tipo JTextField de uma classe de cadastro se tornaram chaves (key) do HashMap<String, JTextField>. Em um diagrama de classes, por exemplo, como faço para detalhar os atributos, já que se tornaram chaves de HashMap e são criados por ele?

 

Ex:

Map<String,JTextField> cadastro = new HashMap<String,JTextField>();   
   cadastro.add("RG", new JTextField());   
   cadastro.add("CPF", new JTextField());   
   cadastro.add("Telefone", new JTextField());

Para ser mais radical na pergunta, imagine que estou usando uma Arquitetura como MVC, onde o desenvolvedor da visão não conhece nada sobre o controle. Porém, o controle deverá conhecer os componentes da visão quando precisar alterar algo no modelo (recolhendo dados das caixas de texto da visão e dando Set's no modelo). Usando HashMap, o desenvolvedor do controlador não saberá quais são os atributos da classe na visão, pois não foram explicitamente instanciados como atributos da classe. Ao ver o diagrama de classes, o programador do controle vai identificar na classe de cadastro o atributo do tipo HashMap no lugar dos atributos do tipo JTextField.

 

Como vou modelar isso em um Diagrama de classes?

Share this post


Link to post
Share on other sites

Bem, vou tentar expor melhor o problema:

 

Vamos imaginar um cadastro qualquer, lá nele alguns JLabel's e JTextField's. (isso na visão)

Veja o código:

 

import javax.swing.*;   
  
class Cadastro {   
  
   private tfNome;   
   private tfSobrenome;   
   private tfRG;   
   // ... Muitos atributos do cadastro.   
  
   Cadastro() {   
	  JPanel painel = new JPanel();   
  
	  painel.add(new JLabel("Nome:"));   
	  tfNome = new JTextField();   
	  painel.add(tfNome);   
  
	  painel.add(new JLabel("Sobreome:"));   
	  tfSobrenome = new JTextField();   
	  painel.add(tfSobrenome);   
  
	  painel.add(new JLabel("R.G:"));   
	  tfRG = new JTextField();   
	  painel.add(tfRG);   
	  // ... Repetindo para todos os atributos.   
   }   
  
   // ... Gets/Sets para todos os atributos.   
}
Agora se eu usar o HashMap, veja só:

import javax.swing.*;   
  
class Cadastro {   
  
   private Map<String,JTextField> cadastro = new HashMap<String,JTextField>();	 
  
   Cadastro() {   
	  JPanel painel = new JPanel();   
  
	  painel.add(new JLabel("Nome:"));   
	  painel.add(cadastro.put("tfNome", new JTextField())); // "put" retorna o objeto inserido na chave.   
	  painel.add(new JLabel("Sobrenome:"));   
	  painel.add(cadastro.put("tfSobrenome", new JTextField()));   
	  painel.add(new JLabel("RG:"));   
	  painel.add(cadastro.put("tfRG", new JTextField()));   
	  // ... Repetindo para todos os atributos. Poderia até fazer um "for" para ler um vetor com as chaves (que tem os nomes dos atributos).   
   }   
   // ... Gets/Sets UNIVERSAIS para todos os atributos. Passa a key para o get e no set passa a key e o valor. Ou seja, dois métodos para todos os atributos.   
}
Veja a redução de código (9 linhas) e a facilidade de manutenção com HASHMAP é incrivelmente superior ao do primeiro caso. Eu posso adicionar/remover (em duas únicas linhas) um JTextField sem a preocupação de ver mais nada, principalmente nos métodos gets/sets. Concorda comigo?

 

O problema todo é: Como vou documentar isso para o pessoal que desenvolve o controle? http://forum.imasters.com.br/public/style_emoticons/default/yay.gif

 

No primeiro caso, a integração do "pessoal que cuida da visão" com o "pessoal que cuida do controle" é praticamente 100%. O pessoal do controle só de bater o olho no Diagrama de Classes do pessoal da visão já identifica os métodos necessários para recolher os dados da visão. Fácil de integrar. http://forum.imasters.com.br/public/style_emoticons/default/joia.gif

 

Já no segundo caso, a integração é praticamente 0% :angry: Visto que se o "pessoal do controle" olhar o Diagrama de Classes do "pessoal da visão" vai ter a surpresa de ver um atributo do tipo HashMap e vai lá saber quais são os nomes das keys (chaves) inseridas nele para identificar Nome, Sobrenome, Rg, etc...

 

Aguardo respostas, sugestões, críticas, não tenha vergonha! O que vale é a opinião. Abração a todos. http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

Share this post


Link to post
Share on other sites

Eu sinceramente não entendo o que vocês estão fazendo. Vocês têm dois diagramas de classe?!

 

O diagrama de classes é um modelo estático que visa descrever a estrutura de um sistema, mostrando as classes com seus atributos e ações; além é claro do relacionamento entre elas. Pra mim, vocês deveriam ter apenas um diagrama de classes. E o mesmo deveria ter sido feito antes de começar a programar.

 

Outra coisa. Você não deve documentar seu sistema voltado para uma tecnologia. Pensa comigo. Você não vai cadastrar um objeto do tipo HashMap, você cadastrará um objeto Cliente (por exemplo). Não importa como você está desenhando seu formulário. Visão é apenas visão.

Share this post


Link to post
Share on other sites

Eu sinceramente não entendo o que vocês estão fazendo. Vocês têm dois diagramas de classe?!

 

O diagrama de classes é um modelo estático que visa descrever a estrutura de um sistema, mostrando as classes com seus atributos e ações; além é claro do relacionamento entre elas. Pra mim, vocês deveriam ter apenas um diagrama de classes. E o mesmo deveria ter sido feito antes de começar a programar.

 

Outra coisa. Você não deve documentar seu sistema voltado para uma tecnologia. Pensa comigo. Você não vai cadastrar um objeto do tipo HashMap, você cadastrará um objeto Cliente (por exemplo). Não importa como você está desenhando seu formulário. Visão é apenas visão.

Olá Vergil, http://forum.imasters.com.br/public/style_emoticons/default/grin.gif

 

Sim, na verdade existe um único diagrama de classes com seus atributos e métodos bem específicos. Foi assim que o exemplo 1 (código) anterior foi criado, com base nele.

Lá está o código da visão. Porém, na visão existe a entrada de dados em JTextField, como pode conferir no mesmo exemplo acima. O controle recebe esses dados, acionando os métodos gets dos atributos de JTextField da visão. Até aí, ótimo. Integração do pessoal que desenvolveu a visão com o pessoal do controle é 100%.

 

Agora imagina no código do exemplo 2. Como estava o diagrama de classes para ele ser criado?

Olhando a classe dele no DC, com certeza você não sabe quem são os atributos... e vai se deparar com um get/set universal.

E aí, como o controle faz para, por exemplo, pegar o nome e sobrenome do JTextField?

 

Aguardo por respostas e agradeço a ajuda de todos. http://forum.imasters.com.br/public/style_emoticons/default/joia.gif Abraço Vergil.

Share this post


Link to post
Share on other sites

Beleza Pedro!

 

Quando li seu post eu logo imaginei a seguinte situação.

 

MODELO

Classe Cliente

atributos nome e cpf

 

CONTROLE

Classe ControlaCliente

public class ControlaCliente {
   private Cliente cliente;

   public ControlaCliente() {
	  cliente = new Cliente();
   }

   // get e set

   public void salva() {
	  // Comandos de persistência
	  // hibernate.saveOrUpdate(cliente);
   }
}

VISÃO

public class CadastraCliente extends JFrame {
   // declaração de componentes GUI - swing
   private Cliente cliente;

   private void acaoBotaoSalvar(Event evt) {
	  ControlaCliente controle = new ControlaCliente();
	  controle.setCliente(cliente);
	  controle.salva();
   }
}

Desse jeito não haveria necessidade de utilizar um monte de parâmetros. A comunicação entre as camadas seria feita através de um objeto do Modelo.

Share this post


Link to post
Share on other sites

Beleza Pedro!

 

Quando li seu post eu logo imaginei a seguinte situação.

 

MODELO

Classe Cliente

atributos nome e cpf

 

CONTROLE

Classe ControlaCliente

public class ControlaCliente {
   private Cliente cliente;

   public ControlaCliente() {
	  cliente = new Cliente();
   }

   // get e set

   public void salva() {
	  // Comandos de persistência
	  // hibernate.saveOrUpdate(cliente);
   }
}

VISÃO

public class CadastraCliente extends JFrame {
   // declaração de componentes GUI - swing
   private Cliente cliente;

   private void acaoBotaoSalvar(Event evt) {
	  ControlaCliente controle = new ControlaCliente();
	  controle.setCliente(cliente);
	  controle.salva();
   }
}

Desse jeito não haveria necessidade de utilizar um monte de parâmetros. A comunicação entre as camadas seria feita através de um objeto do Modelo.

Fala Vergil, obrigado por acompanhar o tópico. http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Rapaz, é uma solução legal. Não sabia que nesse formato era MVC, conhecia completamente diferente.

A visão pode alterar o modelo diretamente sem passar pelo controle?

Mas e se no modelo o atributo RG for do tipo int e lá no JTextField da visão eu digitar letras?

Outra dúvida: Se eu mudar algum atributo no modelo, vou ter que avisar o pessoal da visão para mudar também?

E o controle só salva dados no banco de dados?

Como reenderizo a visão depois do controle salvar o cliente no BD?

Pode me falar mais como funciona esse formato de MVC?

 

[]'s.

Share this post


Link to post
Share on other sites

Fala Vergil, obrigado por acompanhar o tópico. http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Rapaz, é uma solução legal. Não sabia que nesse formato era MVC, conhecia completamente diferente.

A visão pode alterar o modelo diretamente sem passar pelo controle?

Mas e se no modelo o atributo RG for do tipo int e lá no JTextField da visão eu digitar letras?

Outra dúvida: Se eu mudar algum atributo no modelo, vou ter que avisar o pessoal da visão para mudar também?

E o controle só salva dados no banco de dados?

Como reenderizo a visão depois do controle salvar o cliente no BD?

Pode me falar mais como funciona esse formato de MVC?

 

[]'s.

Caramba! Brainstorm... ha ha ha!!!

 

1º Não, a visão não pode alterar o modelo diretamente. O que acontece é que você está preenchendo os valores da variável cliente do controle com um objeto do tipo cliente, cujos dados vieram do formulário.

2º A validação de campos de um formulário pode muito bem ser feita na camada de visão. Eu pelo menos acho o mais adequado.

3º Em qualquer situação, se você modifica o modelo terá que modificar a visão. Imagine que você tenha a classe persistente Cliente. Se você acrescentar um atributo dataNascimento na classe (base de dados), naturalmente você terá que acrescentar este campo na visão (formulário) para que o usuário o preencha. Contudo, o controle nem precisará saber disso.

4º A camada de controle pode salvar os dados onde quiser. Seja numa tabela de banco de dados, um arquivo txt, xml ou até todos esses se for necessário. Isso vai depender da implementação do método salva.

5º O controle tem métodos get e set para o objeto modelo. No exemplo que eu citei: Cliente. A camada de visão receberá os valores da camada de controle através do get.

Share this post


Link to post
Share on other sites

Fala Vergil, obrigado por acompanhar o tópico. http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Rapaz, é uma solução legal. Não sabia que nesse formato era MVC, conhecia completamente diferente.

A visão pode alterar o modelo diretamente sem passar pelo controle?

Mas e se no modelo o atributo RG for do tipo int e lá no JTextField da visão eu digitar letras?

Outra dúvida: Se eu mudar algum atributo no modelo, vou ter que avisar o pessoal da visão para mudar também?

E o controle só salva dados no banco de dados?

Como reenderizo a visão depois do controle salvar o cliente no BD?

Pode me falar mais como funciona esse formato de MVC?

 

[]'s.

Caramba! Brainstorm... ha ha ha!!!

 

1º Não, a visão não pode alterar o modelo diretamente. O que acontece é que você está preenchendo os valores da variável cliente do controle com um objeto do tipo cliente, cujos dados vieram do formulário.

2º A validação de campos de um formulário pode muito bem ser feita na camada de visão. Eu pelo menos acho o mais adequado.

3º Em qualquer situação, se você modifica o modelo terá que modificar a visão. Imagine que você tenha a classe persistente Cliente. Se você acrescentar um atributo dataNascimento na classe (base de dados), naturalmente você terá que acrescentar este campo na visão (formulário) para que o usuário o preencha. Contudo, o controle nem precisará saber disso.

4º A camada de controle pode salvar os dados onde quiser. Seja numa tabela de banco de dados, um arquivo txt, xml ou até todos esses se for necessário. Isso vai depender da implementação do método salva.

5º O controle tem métodos get e set para o objeto modelo. No exemplo que eu citei: Cliente. A camada de visão receberá os valores da camada de controle através do get.

 

Olá Vergil, tudo bom rapaz? Obrigado por estar acompanhando o tópico! http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Me desculpa, antes de tudo, discordar contigo em alguns pontos. http://forum.imasters.com.br/public/style_emoticons/default/ermm.gif

Se eu validar dados na visão e tiver várias visões, vou ter que repetir a validação em todas as visões.

Se eu adicionar um atributo na classe persistente vou ter que adicionar sim na visão. Porém, no controle também, afinal, na hora de reenderizar a visão quem vai colocar o valor lá é o get do controle.

 

Mas para não perder o foco da questão, a sua idéia de usar uma classe do próprio modelo para transportar os dados da visão para o controle é interessante. Se não fosse o inconveniente da validação (quando falo em validação, falo também sobre "tipos" diferentes como String, int, double, boolean...), seria uma ótima solução.

 

Espero mais respostas de todos que estiverem a fim de ajudar!

Quero agradecer antecipadamente por estar lendo este tópico, independente de responde-lo ou não. ;)

Obrigado, fico no aguardo.

Share this post


Link to post
Share on other sites

Beleza, cara!

 

Não há problemas em discordar. Afinal, estamos aqui pra trocar experiência.

 

1º Eu acho melhor validar os dados na visão devido ao fato de já ter controles pra validação utilizando o framework JSF (para aplicações WEB). Assim não é preciso fazer novas requisições. A requisição só é feita após a validação do formulário.

 

2º Se você utilizar o método do qual comentei você não precisará acrescentar nada no controle. Você terá que adicionar apenas na visão. Agora, se você tiver um método get e set para cada atributo da sua classe no controle, aí sim você terá que adicionar o atributo.

 

Agora estou me situando. Você deve estar trabalhando com o mesmo modelo do NetBeans Visual Web Pack. É interessante, apesar de sujar um pouco o controle com instâncias de objetos gui. Se na visão você tem um objeto textfield, no controle você terá uma instância de um textfield que faça referência ao textfield da visão. Esse modelo funciona bem quando você tem a IDE pra auxiliar, fazendo links automáticos.

 

Eu faria do jeito que comentei desde o início. Porém, para uma aplicação desktop, deixaria a validação no controle mesmo. Teria um método valida() do tipo String no controle que retornaria null caso todos os campos passassem no teste ou uma mensagem de erro personalizada caso contrário.

Share this post


Link to post
Share on other sites

Fala Vergil, boa noite! Obrigado por estar acompanhando! http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Agora estou me situando. Você deve estar trabalhando com o mesmo modelo do NetBeans Visual Web Pack. É interessante, apesar de sujar um pouco o controle com instâncias de objetos gui. Se na visão você tem um objeto textfield, no controle você terá uma instância de um textfield que faça referência ao textfield da visão. Esse modelo funciona bem quando você tem a IDE pra auxiliar, fazendo links automáticos.

 

Eu faria do jeito que comentei desde o início. Porém, para uma aplicação desktop, deixaria a validação no controle mesmo. Teria um método valida() do tipo String no controle que retornaria null caso todos os campos passassem no teste ou uma mensagem de erro personalizada caso contrário.

Quase isso. Na verdade, o controle, em seu construtor, recebe como referência uma instancia da visão e uma do modelo.

Então dentro da classe crio dois atributos, um com tipo visão e outro com tipo modelo que receberam as referências vindas do construtor.

class Controle {

   Modelo m;
   Visao v;

   Controle (Modelo m, Visao v) {
	  this.m = m;
	  this.v = v;
   }

   // Classes internas para receber os eventos da visao.
}
A partir daí para atualizar a visão, utilizo os set's da visão ( Ex. v.setNome("pedro"); ), que trazem os dados vindos do modelo.

E para receber os dados da visão (no caso de formulário) utilizo os get's da visão, que trasem os dados dela, passam por uma validação no controle e, se obter sucesso, atualiza o modelo.

 

O que pretendia era uma forma de criar visões mais limpas, com menos linhas e com gets/sets universais para o mesmo tipo. Por isso pensei no HashMap.

O duro é, por exemplo, ficar claro o nome dos atributos lá na visão, já que esses nomes existiriam na classe mas não como atributos e sim chaves (keys) do HashMap.

No diagrama de classes a classe da visão teria como atributo um HASHMAP, sem maiores explicações. Como a pessoa que está fazendo o controle vai saber os nomes das chaves, visto que não ah mais nada a dizer para ele a não ser ele abrindo o programadavisao.java e olhando lá os nomes da chave?

 

Valew Vergel pela paciência, desculpa sou mesmo brainstorm! http://forum.imasters.com.br/public/style_emoticons/default/yay.gif

Share this post


Link to post
Share on other sites

Codifiquei um caso bem simples pra ilustrar a implementação da qual tenho falado. Imagine um dicionário. Basicamente ele tem dois atributos: palavra e definição. Dessa forma criei uma classe Dicionario_Dados do tipo entidade.

 

MODELO

package siscap.model.dicionario;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 *
 * @author Vergil
 */
@Entity
public class Dicionario_Dados implements Serializable {

	@Id
	@GeneratedValue
	private Integer id;
	@Column(length=40, nullable=false, unique=true)
	private String nomeItem;
	@Column(length=200, nullable=false)
	private String definicao;

	public Dicionario_Dados() {
		this.id = null;
		this.nomeItem = this.definicao = null;
	}

	public Integer getId() {
		return id;
	}

	public String getNomeItem() {
		return nomeItem;
	}

	public String getDefinicao() {
		return definicao;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public void setNomeItem(String nomeItem) {
		this.nomeItem = nomeItem;
	}

	public void setDefinicao(String definicao) {
		this.definicao = definicao;
	}
}

Veja que nessa situação não é necessário mudar nada (exceto o método valida, claro) no controle quando acrescentado algum campo no modelo.

Obs.: Eu poderia fazer tratamento de excessão no controle para também retornar mensagem personalizada. Mas essa não é a intenção no momento.

CONTROLE

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package siscap.controller.dicionario;

import java.util.List;
import siscap.model.dicionario.Dicionario_Dados;
import siscap.utilitarios.DAOFactory;

/**
 *
 * @author Vergil
 */
public class ControleDicionarioDados {

	private Dicionario_Dados dicionarioDados;

	public ControleDicionarioDados() {
		this.dicionarioDados = new Dicionario_Dados();
	}

	public ControleDicionarioDados(Dicionario_Dados dicionario) {
		this.dicionarioDados = dicionario;
	}

	public Dicionario_Dados getDicionarioDados() {
		return dicionarioDados;
	}

	public void setDicionarioDados(Dicionario_Dados dicionarioDados) {
		this.dicionarioDados = dicionarioDados;
	}
	
	public List listaDicionario() {
		DAOFactory daoFactory = new DAOFactory();
		daoFactory.beginTransaction();
		List lista = daoFactory.getDicionario_Dados().listar();
		daoFactory.close();
		return lista;
	}

	public String adiciona() {
		String mensagem = this.valida();
		if(mensagem != null) {
			return mensagem;
		}
		
		DAOFactory daoFactory = new DAOFactory();
		daoFactory.beginTransaction();
		daoFactory.getDicionario_Dados().adicionar(this.dicionarioDados);
		daoFactory.commit();
		daoFactory.close();
		return "O ítem '" + this.dicionarioDados.getNomeItem() + "' foi salvo com sucesso!";
	}

	public String atualiza() {
		String mensagem = this.valida();
		if(mensagem == null) {
			return mensagem;
		}
		
		DAOFactory daoFactory = new DAOFactory();
		daoFactory.beginTransaction();
		daoFactory.getDicionario_Dados().atualizar(this.dicionarioDados);
		daoFactory.commit();
		daoFactory.close();
		return "O ítem '" + this.dicionarioDados.getNomeItem() + "' foi salvo com sucesso!";
	}

	public String remove() {		
		DAOFactory daoFactory = new DAOFactory();
		daoFactory.beginTransaction();
		daoFactory.getDicionario_Dados().remover(this.dicionarioDados);
		daoFactory.commit();
		daoFactory.close();
		return "O ítem '" + this.dicionarioDados.getNomeItem() + "' foi removido com sucesso!";
	}

	private String valida() {
		String mensagem = "";
		if(this.dicionarioDados.getNomeItem() == null ||
				this.dicionarioDados.getNomeItem().equals("")) {
			mensagem = "Campo 'nome do ítem' requerido.\n";
		}

		if(this.dicionarioDados.getDefinicao() == null ||
				this.dicionarioDados.getDefinicao().equals("")) {
			mensagem += "Campo 'definição' requerido.";
		}

		return (mensagem.equals("") ? null : mensagem);
	}
}

VISAO

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package siscap.view.dicionario;

import javax.swing.JOptionPane;
import siscap.controller.dicionario.ControleDicionarioDados;
import siscap.model.dicionario.Dicionario_Dados;

/**
 *
 * @author Vergil
 */
public class NovoItemDicionario extends javax.swing.JDialog {

	/** Creates new form NovoItemDicionario */
	public NovoItemDicionario(java.awt.Frame parent, boolean modal) {
		super(parent, modal);
		initComponents();
		this.dicionarioDados = new Dicionario_Dados();
	}

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
	private void initComponents() {
		// Código de configuração de componentes gráficos (GUI) gerado pelo IDE
	}// </editor-fold>//GEN-END:initComponents

	private void ButtonCancelarActionPerformed(java.awt.event.ActionEvent evt) {
		this.cancela();
	}

	private void ButtonSalvarActionPerformed(java.awt.event.ActionEvent evt) {
		this.salva();
	}

	private void salva() {
		this.setEntidade();
		ControleDicionarioDados controle = new ControleDicionarioDados();
		controle.setDicionarioDados(this.dicionarioDados);
		// ou ControleDicionarioDados controle = new ControleDicionarioDados(this.dicionarioDados);
		String mensagem = controle.adiciona();
		JOptionPane.showMessageDialog(this, mensagem);
	}

	private void cancela() {
		this.TextFieldPalavra.setText("");
		this.TextAreaDefinicao.setText("");
	}
	
	private void setEntidade() {
		this.dicionarioDados.setNomeItem(this.TextFieldPalavra.getText());
		this.dicionarioDados.setDefinicao(this.TextAreaDefinicao.getText());
	}

	/**
	* @param args the command line arguments
	*/
	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {
			public void run() {
				NovoItemDicionario dialog = new NovoItemDicionario(new javax.swing.JFrame(), true);
				dialog.addWindowListener(new java.awt.event.WindowAdapter() {
					public void windowClosing(java.awt.event.WindowEvent e) {
						System.exit(0);
					}
				});
				dialog.setVisible(true);
			}
		});
	}

	private Dicionario_Dados dicionarioDados;
	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.JButton ButtonCancelar;
	private javax.swing.JButton ButtonSalvar;
	private javax.swing.JLabel LabelDefinicao;
	private javax.swing.JLabel LabelPalavra;
	private javax.swing.JScrollPane ScrollPaneDefinicao;
	private javax.swing.JTextArea TextAreaDefinicao;
	private javax.swing.JTextField TextFieldPalavra;
	// End of variables declaration//GEN-END:variables

}

Dessa maneira fica fácil seguir o diagrama de classes, e principalmente, tornando-o independente da tecnologia utilizada.

Share this post


Link to post
Share on other sites

Neste caso não utilizei nenhum framework. Só utilizei o NetBeans como ferramenta RAD.

Share this post


Link to post
Share on other sites

Estive pensando se existe algum framework que implementa a arquitetura MVC para desktop como JSF, Struts, etc. implementam para aplicações web. Pesquisei no oráculo e nada achei. A forma da qual ilustrei, é uma opção para separar as camadas de uma maneira leve. Acredito que para implementar MVC em aplicações desktop você deveria seguir as implementações dos componentes swing. Um objeto JTable tem um TableModel, eventos (addAction setAction) e métodos de desenho (visão). Uma vez li um artigo bastante interessante no JavaWorld. É bastante esclarecedor. Eles deram como exemplo um objeto JButton. Olha o que diz nessa frase: "The model defines the button's behavior and the view/controller defines its appearence." O modelo define o comportamento do botão e a visão/controle define sua aparência. O link para o artigo é esse http://www.javaworld.com/javaworld/jw-04-1...wto.html?page=1

Share this post


Link to post
Share on other sites

Pensei numa outra forma de implementação na qual a visão poderá ser usada para salvar um objeto (inserir / atualizar). Eu dividi a camada de controle em arquivos de ação. Na visão eu tenho um campo do tipo entidade que seria o modelo do objeto visão. Partindo da mesma linha de raciocínio do dicionário de dados teremos a seguinte implementação:

 

MODELO

package siscap.model.dicionario;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 *
 * @author Aureliano
 */
@Entity
public class Dicionario_Dados implements Serializable {

	@Id
	@GeneratedValue
	private Integer id;
	@Column(length=40, nullable=false, unique=true)
	private String nomeItem;
	@Column(length=200, nullable=false)
	private String definicao;

	public Dicionario_Dados() {
		this.id = null;
		this.nomeItem = this.definicao = null;
	}
	
	public Dicionario_Dados(String nomeItem, String definicao) {
		this.nomeItem = nomeItem;
		this.definicao = definicao;
	}

	public Integer getId() {
		return id;
	}

	public String getNomeItem() {
		return nomeItem;
	}

	public String getDefinicao() {
		return definicao;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public void setNomeItem(String nomeItem) {
		this.nomeItem = nomeItem;
	}

	public void setDefinicao(String definicao) {
		this.definicao = definicao;
	}
}

CONTROLE

Validação de campos e método para salvar entidade

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package siscap.controller.dicionario;

import java.util.List;
import siscap.model.dicionario.Dicionario_Dados;
import siscap.utilitarios.DAOFactory;

/**
 *
 * @author Aureliano
 */
public class ControleDicionarioDados {

	private Dicionario_Dados dicionarioDados;

	public ControleDicionarioDados() {
		this.dicionarioDados = new Dicionario_Dados();
	}

	public Dicionario_Dados getDicionarioDados() {
		return dicionarioDados;
	}

	public void setDicionarioDados(Dicionario_Dados dicionarioDados) {
		this.dicionarioDados = dicionarioDados;
	}
	
	public List listaDicionario() {
		DAOFactory daoFactory = new DAOFactory();
		daoFactory.beginTransaction();
		List lista = daoFactory.getDicionario_Dados().listar();
		daoFactory.close();
		return lista;
	}
	
	public String salva() {
		String mensagem = this.valida();
		if(mensagem != null) {
			return mensagem;
		}
		
		DAOFactory daoFactory = new DAOFactory();
		daoFactory.beginTransaction();
		daoFactory.getDicionario_Dados().salvar(this.dicionarioDados); // chama saveOrUpdate(entidade); de Hibernate Session
		daoFactory.commit();
		daoFactory.close();
		return "O ítem '" + this.dicionarioDados.getNomeItem() + "' foi salvo com sucesso!";
	}

	public String remove() {		
		DAOFactory daoFactory = new DAOFactory();
		daoFactory.beginTransaction();
		daoFactory.getDicionario_Dados().remover(this.dicionarioDados);
		daoFactory.commit();
		daoFactory.close();
		return "O ítem '" + this.dicionarioDados.getNomeItem() + "' foi removido com sucesso!";
	}

	private String valida() {
		String mensagem = "";
		if(this.dicionarioDados.getNomeItem() == null ||
				this.dicionarioDados.getNomeItem().equals("")) {
			mensagem = "Campo 'nome do ítem' requerido.\n";
		}

		if(this.dicionarioDados.getDefinicao() == null ||
				this.dicionarioDados.getDefinicao().equals("")) {
			mensagem += "Campo 'definição' requerido.";
		}

		return (mensagem.equals("") ? null : mensagem);
	}
}

Ação de carregar os campos do formulário com os valores do modelo - WindowOpened

package siscap.controller.dicionario;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import siscap.model.dicionario.Dicionario_Dados;
import siscap.view.dicionario.VisaoDicionarioDados;

/**
 *
 * @author Aureliano
 */
public class CarregaDicionario extends WindowAdapter {

	public CarregaDicionario() {

	}
	
	@Override
	public void windowOpened(WindowEvent evt) {
		this.carregaDicionario();
	}

	private void carregaDicionario() {
		Dicionario_Dados valor = VisaoDicionarioDados.getDicionarioDados();
		VisaoDicionarioDados.setPalavra(valor.getNomeItem());
		VisaoDicionarioDados.setDefinicao(valor.getDefinicao());
	}
}

Ação de limpar os campos do formulário / deixá-lo no estado inicial. Se o textfield inicia com o valor "", essa ação recupera esse valor pro textfield. Se for "texto", o valor "texto" será atribuído ao textfield.

package siscap.controller.dicionario;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import siscap.model.dicionario.Dicionario_Dados;
import siscap.view.dicionario.VisaoDicionarioDados;

/**
 *
 * @author Aureliano
 */
public class AcaoLimparFormulario implements ActionListener {

	public AcaoLimparFormulario() {
		
	}
	
	public void actionPerformed(ActionEvent evt) {
		this.limpaFormulario();
	}

	private void limpaFormulario() {
		Dicionario_Dados valor = VisaoDicionarioDados.getDicionarioDados();
		VisaoDicionarioDados.setPalavra(valor.getNomeItem());
		VisaoDicionarioDados.setDefinicao(valor.getDefinicao());
	}
}

Ação de salvar a entidade. Chama o método salva() de ControleDicionario.

package siscap.controller.dicionario;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import siscap.model.dicionario.Dicionario_Dados;
import siscap.view.dicionario.VisaoDicionarioDados;

/**
 *
 * @author Vergil
 */
public class AcaoSalvar implements ActionListener {

	public AcaoSalvar() {

	}

	public void actionPerformed(ActionEvent e) {
		this.salvaFormulario();
	}

	private void salvaFormulario() {
		ControleDicionarioDados controle = new ControleDicionarioDados();
		Dicionario_Dados valor = new Dicionario_Dados();
		valor.setNomeItem(VisaoDicionarioDados.getPalavra());
		valor.setDefinicao(VisaoDicionarioDados.getDefinicao());
		controle.setDicionarioDados(valor);
		String mensagem = controle.salva();
		JOptionPane.showMessageDialog(null, mensagem);
	}
}

VISÃO

package siscap.view.dicionario;

import siscap.controller.dicionario.AcaoLimparFormulario;
import siscap.controller.dicionario.AcaoSalvar;
import siscap.controller.dicionario.CarregaDicionario;
import siscap.model.dicionario.Dicionario_Dados;

/**
 *
 * @author Aureliano
 */
public class VisaoDicionarioDados extends javax.swing.JDialog {

	/** Creates new form VisaoDicionarioDados */
	public VisaoDicionarioDados(java.awt.Frame parent, boolean modal, Dicionario_Dados dicionario) {
		super(parent, modal);
		initComponents();
	}

	@SuppressWarnings("unchecked")
	private void initComponents() {
		// iniciação dos componentes gráficos.
		dicionarioDados = dicionario;
		super.addWindowListener(new CarregaDicionario());
		this.ButtonCancelar.addActionListener(new AcaoLimparFormulario());
		this.ButtonSalvar.addActionListener(new AcaoSalvar());
	}

	public static void setDicionarioDados(Dicionario_Dados dados) {
		dicionarioDados = dados;
	}

	public static Dicionario_Dados getDicionarioDados() {
		return dicionarioDados;
	}

	public static void setPalavra(String palavra) {
		TextFieldPalavra.setText(palavra);
	}

	public static String getPalavra() {
		return TextFieldPalavra.getText();
	}

	public static void setDefinicao(String definicao) {
		TextAreaDefinicao.setText(definicao);
	}

	public static String getDefinicao() {
		return TextAreaDefinicao.getText();
	}

	private static Dicionario_Dados dicionarioDados;
	private javax.swing.JButton ButtonCancelar;
	private javax.swing.JButton ButtonSalvar;
	private javax.swing.JLabel LabelDefinicao;
	private javax.swing.JLabel LabelPalavra;
	private javax.swing.JScrollPane ScrollPaneDefinicao;
	private static javax.swing.JTextArea TextAreaDefinicao;
	private static javax.swing.JTextField TextFieldPalavra;
}

Neste caso eu utilizei uma janela Principal.java herdando de JFrame com um menu chamando a janela do dicionário de dados.

VisaoDicionarioDados frameNovoItem = new VisaoDicionarioDados(this, true, new Dicionario_Dados());

// ou VisaoDicionarioDados frameNovoItem = new VisaoDicionarioDados(this, true, new Dicionario_Dados("palavra carregada", "definiçãoo carregada"));

frameNovoItem.setVisible(true);

 

Aqui segue um link do vídeo para demonstração do seu funcionamento.

Na primeira parte eu utilizei a instância padrão de VisaoDicionarioDados, na segunda a sobrecarregada.

Share this post


Link to post
Share on other sites

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.