@viny_2 escreveu:
Olá programadores!
Estou desenvolvendo uma aplicação para fins didáticos, trabalho da faculdade de final de semestre, neste irá fazer CRUD das disciplinas em uma tabela no banco já criada, "DISCIPLINES", pensei em criar uma lista de processos, caso o usuário deseje refazer suas alterações, tipo crt+z, é após fazer as alterações e estar certo disto, executar as alterações. deste modo:
O usuário faz uma operação de crud pela interface gráfica, e após as alterações, ao clicar em OK, executa a lista de processos.
segue o código dos métodos que gera, deleta e executa os processos://Implentação da interface omitidos @Override public void setupEvents() { //evento do botão deletar disciplina btnDelete.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int rowIndex = tbListDisciplines.getSelectedRow(); int id = (int)tbListDisciplines.getModel().getValueAt(rowIndex, 0); InvokerRemove delete = new InvokerRemove(id, new ControllerDiscipline()); queue.addProcess(delete); lblAmountDisciplines.setText("" + tbListDisciplines.getRowCount()); model.remove(rowIndex); } }); //evento do botão alterar disciplina btnEdit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int rowIndex = tbListDisciplines.getSelectedRow(); int id = (int)tbListDisciplines.getModel().getValueAt(rowIndex, 0); String name = tfNameDiscipline.getText(); InvokerUpdateRefatorar update = new InvokerUpdateRefatorar(id, name, new ControllerDiscipline()); queue.addProcess(update); System.out.println(name); Discipline marca = new Discipline(); marca.setName(tfNameDiscipline.getText()); model.update(rowIndex, marca); } }); //evento que finaliza as alterações e executa os processos de crud. btnOk.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { glassPanel.start(); queue.executeProcess(); model.clearlistRemoved(); Thread performer = new Thread(new Runnable() { public void run() { perform(); } }, "Performer"); performer.start(); } }); //evento do botão cancelar, e invoca o método sair. btnCancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { quit(); } }); //MouseListener para preencher o textField tbListDisciplines.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { int rowIndex = tbListDisciplines.getSelectedRow(); tfNameDiscipline.setText((String)tbListDisciplines.getModel().getValueAt(rowIndex, 1)); } }); } //outros métodos omitidos
Caso o usuário deseja desfazer a alteração, ele clica em cancelar (eu ainda estou implementado uma forma melhor de fazer isso, por exemplo, crt+z para desfazer a ultima alteração) código a baixo:
@Override public void quit() { if(!model.isEmptyList()){ int confirm = JOptionPane.showConfirmDialog(this, "Deseja sair, as alterações feita não serão salvas ?", "Desistir das alterações?", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE); if(confirm == JOptionPane.YES_OPTION) { this.dispose(); model.clearlistRemoved(); } } else{ this.dispose(); } }
apenas por uma questão de beleza adicionei um glassPane para simular um processo coisa bem simples.
Na questão de gerar a lista de processos eu estou utilizando o Pattern Command, crie uma queue de processos, QueuesProcess, que será responsável por receber todas as "operações de crud" segue o código:/** * Classe responsável por criar uma fila de processos, CRUD, * remove processos da fila para casos de refazer as decisões anteriores * e limpa a fila para os próximos processos. * <br><br> * Nome do projeto: MeOrganize <br> * Integra ao pocote: utfpr.tsi.meOrganize.controller.impl<br> * @author Vinicius Cavalcanti * @since implementação da aplicação * @version 1.0v 2016 */ public class QueuesProcess { private Queue<IECommand> process; /** * construtor inicializa a lista de processos */ public QueuesProcess() { process = new LinkedList(); } /** * Método que adiciona processos a lista * @param process - o processo que será adicionado a fila */ public void addProcess(IECommand process) { this.process.add(process); } /** * Método que remove um processo adicionado * @param process - processo que será removido */ public void removeProcess(IECommand process) { this.process.remove(process); } /** * Método que limpa a lista para casos * de sair da janela e cancelar as operações (CRUD) */ public void clearQueues() { this.process.clear(); } /** * Método que executa as operações na fila e limpa a fila. */ public void executeProcess() { for(IECommand command : this.process) command.execute(); process.clear(); } }
Bem como havia dito estou usando o pattern command, sendo assim criei uma interface IEcommand para o contrato dos invoker com apenas o comando executar. Seque os código abaixo:
/** * Contrato da fila de comandos CRUD. * <br><br> * Nome do projeto: MeOrganize <br> * Integra ao pocote: utfpr.tsi.meOrganize.controller<br> * @author Vinicius Cavalcanti * @since * @version 2016 */ public interface IECommand { void execute(); }
E uma classe abstrata para os pedidos de crud, vou criar um controller para cada tabela, neste caso estou mostrando apenas das disciplinas, mas, terá outras entidades, como por exemplo, a agenda de estudo, o planejamento.
/** * Classe abstrata responsável pelos pedidos de Crud * para camada dao, antes de inserir faz uma busca no banco * para verificar se a entidade já existe e retonar o resultado. * <br><br> * Nome do projeto: MeOrganize <br> * Integra ao pocote: utfpr.tsi.meOrganize.controller.impl<br> * @author Vinicius Cavalcanti * @since implentação da aplicação * @version 1.0c 2016 * @param <T> entidade * @param <E> qual dao será utilizado. */ public abstract class Controller<T, E> implements IERegister<T, E>{ protected IEDAO dao; protected IEEntity entity; public Controller(IEDAO dao, IEEntity entity) { this.dao = dao; this.entity = entity; } /** * Método responsável por pedir a camada dao a inserção * na tabela da entidade. * @return - retorna true se a inserção foi feita, false se não é o erro. * @throws - erro se a entidade veio nula. */ public boolean add(String name) throws EntityNull { this.entity.setName(name); if(exists() == false) { try { dao.insert(entity); } catch (EntityNull | ClassNotFoundException e) { System.out.println("Não foi possivel adicionar ao banco porque:\n" + e.getMessage()); } return true; } return false; } /** * Método responsável por pedir a remoção da entidade da tabela. * A remoção e feita por uma busca pelo id da entidade. * @return - retorna true se a remoção foi feita, false se não é o erro. * @throws - erro se a entidade veio nula. */ public boolean remove(int id) throws EntityNull{ try { this.dao.remove(id); } catch (EntityNull | ClassNotFoundException e) { System.out.println("Não foi possível remover porque:\n" + e.getMessage()); } return false; } /** * Método responsável por pedir a camada dao a alteração na entidade. * faz uma busca pelo id da entidade e pede a alteração. * @throws - erro se a entidade veio nula. */ public void update(int id, String name) throws EntityNull{ this.entity.setId(id); this.entity.setName(name); try { this.dao.update(entity); } catch (ClassNotFoundException e) { System.out.println("Não foi possivel atualizar a entidade no banco porque:\n" + e.getMessage()); } } /** * Método que verifica se a entidade já existe na tabale. * faz uma busca na tabela pela entidade * @return true se a entidade já existe, falso se não. */ public boolean exists() { ArrayList<IEEntity<T>> entitys = new ArrayList<>(); try { entitys.addAll(dao.searchData()); } catch (ClassNotFoundException e) { System.out.println("Não foi possivel fazer a busca no banco porque:\n" + e.getMessage()); } for(IEEntity enti : entitys) { if(entity.getName().equals(enti.getName())) { JOptionPane.showMessageDialog(null, "Entidade já existe", "Erro no cadastro da entidade", JOptionPane.ERROR_MESSAGE); return true; } } return false; } } /** * Contrato de controller das classe que recebe os dados * para envidar para a camada DAO para manipular os dados das entidadades * do banco de dados. * <br><br> * Nome do projeto: MeOrganize <br> * Integra ao pocote: utfpr.tsi.meOrganize.controller<br> * @author Vinicius Cavalcanti * @since implementação da aplicação * @version 1.0v 2016 * @param <T> Entidade que será passado para camada DAO. * @param <E> Dao que será utilizado para entidade. */ public interface IERegister<T, E> { /** * Método responsável para enviar a camada DAO a entidade para salvar * @param obj a entidade * @throws EntityNull exceção de entidade nula. */ boolean add(String name) throws EntityNull; /** * Método responsável para enviar a camada DAO a entidade, por parâmetro o id, * que será deletado. * @param id - O id da entidade * @throws EntityNull exceção de entidade nula. */ boolean remove(int id) throws EntityNull; /** * Método que verifica se a entidade já existe ou não * @param dao * @param entity * @return true para existe e false para não existe. */ boolean existsDiscipline(T dao, E entity); /** * Método responsável para enviar a camada DAO a entidade, por parâmentro o id, * que será alterado. * @param id - O id da entidade. * @throws EntityNull exceção de entidade nula. */ void update(int id, String name) throws EntityNull; }
Outra classe que herda os métodos da classe abstrata para fazer o crud, neste caso das disciplinas.
/** * Classe concreta responsável por gerenciar os pedidos de crud * para camada dao. * <br><br> * Nome do projeto: MeOrganize <br> * Integra ao pocote: utfpr.tsi.meOrganize.controller.impl<br> * @author Vinicius Cavalcanti * @since implementação da aplicação * @version 1.0v 2016 */ public class ControllerDiscipline extends Controller{ /** * construtor que manda para super classe um * entidade criada pelo dao. */ public ControllerDiscipline() { super(new DisciplineDAO(), new DisciplineDAO().create()); } /** * Método que faz a inserção. * @return true se inserção bem sucedida false se não. * @throws - exceção se a entidade está nula */ public boolean add(String name) throws EntityNull{ return super.add(name); } /** * Método que faz a remoção. * @return true se remoção bem sucedida false se não. * @throws - exceção se a entidade está nula */ public boolean remove(int id) throws EntityNull{ return super.remove(id); } /** * Método que faz a alteração. * @return true se alteração bem sucedida false se não. * @throws - exceção se a entidade está nula */ public void update(int id, String name) throws EntityNull { super.update(id, name); } /** * Método que verifica se a entidade já existe. * @return true se sim. false se não. */ @Override public boolean existsDiscipline(Object dao, Object entity) { return false; } }
Bem explicado o contexto. Agora é que vêm a minha dúvida se estou fazendo certo, pois nosso professor vai avaliar a elegância do código também, não basta estar funcionando, o trabalho "sistema" devera estar bem escrito, com uso moderado de patterns e uma estrutura boa.
Eu criei uma classe para cada crud (InvokerAdd, IinvokerRemove, InvokerUpdate) como vocês podem ver no código da interface, eu crio um remover, e instancio no fila.btnDelete.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int rowIndex = tbListDisciplines.getSelectedRow(); int id = (int)tbListDisciplines.getModel().getValueAt(rowIndex, 0); InvokerRemove delete = new InvokerRemove(id, new ControllerDiscipline()); queue.addProcess(delete); lblAmountDisciplines.setText("" + tbListDisciplines.getRowCount()); model.remove(rowIndex); } });
Que vai popular a fila de processos. com apenas um método. Vou postar apenas a de adicionar mas, serve para todas, unica alteração é os parâmetros, em pensei em fazer uma sobre carga de métodos trocando os parâmetros não, sempre que eu adicionar um novo "método" estou quebrando o principio (OpenClose) do solid?
Vocês poderiam me aconselhar em uma melhor implementação?
Mensagens: 1
Participantes: 1