Design Pattern Observer com aplicação Swing (JSE)

Como já comentado em outros artigos (posts), um Padrão de Projeto (Design Pattern) não depende de linguagem ou mesmo tecnologia, quando falamos em padrões tratamos de soluções que são comprovadamente eficientes e que garantem o funcionamento do que se propõe realizar.

Cenário do Problema

Como acoplar objetos que somente estarão relacionados em tempo de execução? Este acoplamento deve ser flexível o suficiente para ser ajustado em tempo de execução. O Padrão Observer permite realizar a atualização dos estados entre objetos através da troca de mensagens coordenadas entre observador(Listener ou Ouvinte) e observado (Source ou Fonte). Para o caso da proposta deste trabalho consideremos a arquitetura MVC, onde as classes estão empacotadas na camada Model, sendo exibidas pela View e gerenciadas pela Controller. Desta maneira, quando a classe de controle criar uma instância de um Modelo (Model), construir uma janela (View) e encaminhar para a janela exibida o objeto para a realização das posteriores implementações. Um dos principais problemas podem ocorrer é a manutenção da sincronização dos estados entre o Controller, Model e View, ou seja, o fato da janela precisar avisar a classe controladora que o objeto modelo já foi preenchido, e que agora se deve realizar a persistência da mesma. A proposta da utilização do Observer não é a única solução, mas é indicada em muitos dos casos.

Design Pattern Observer

O design pattern Observer, segundo Freeman et al, define uma dependência um-para-muitos entre objetos de modo que,  quando um objeto muda de estado, todos os seus dependentes são notificados e atualizados automaticamente. Considerando agora os princípios da Orientação a Objetos que nos diz para encapsular o que varia, dando prioridade a composição (implementação de interfaces) em relação à herança, é possível modelar os projetos levemente ligados entre objetos que interagem.

Aplicação Observer com Swing

Para esta aplicação, foram desenvolvidas 3 Classes, cada uma abordando os conceitos de MVC, sendo respectivamente Model, View e Controller os nomes das classes. Para a implementação do Design Pattern, foi utilizado as Classes: java.util.Observable e import java.util.Observer. padrão da linguagem Java. O diagrama implementado é o seguinte:

ObserverObservablePatternizando

Modelo de Projeto Observer Observable

Pode-se observar no diagrama e na codificação da Classe modelo que ela estende java.util.Observable, ou seja, ela será observada pelas classes View e Controller. Esta “observação” é criada quando, na Controller é adicionado por meio do método addObserver(). Um detalhe importante é que as classe que “podem observar”, necessariamente implementam a interface java.util.Observer.

Código da Classe Model:

import java.util.Observable;
public class Model extends Observable{

    private String campo1;
    private Integer campo2;

    public void atualizar(String campo1, Integer campo2){
        this.campo1 = campo1;
        this.campo2 = campo2;

        //Métodos que "avisam" os observadores
        notifyObservers();
        setChanged();
    }

    public String getCampo1() {
        return campo1;
    }

    public void setCampo1(String campo1) {
        this.campo1 = campo1;
    }

    public Integer getCampo2() {
        return campo2;
    }

    public void setCampo2(Integer campo2) {
        this.campo2 = campo2;
    }
}

Nas Classes abaixo verifica-se o método update(), implementado devido a interface java.util.Observer. Este método é invocado quando a classe Observable, no caso deste projeto à View, invocar o método notifyObserver().

Código da Classe View:

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class View extends JFrame implements Observer{

    private Model model;
    private JPanel pnlCampo1;
    private JPanel pnlCampo2;
    private JPanel pnlBotao;
    private JLabel lblCampo1;
    private JLabel lblCampo2;
    private JTextField txtCampo1;
    private JTextField txtCampo2;
    private JButton botao;

    public View(String titulo, Model model){
        super(titulo);
        this.model = model;
        renderizarComponentes();
    }

    public void renderizarComponentes(){
        pnlCampo1 = new JPanel();
        pnlCampo2 = new JPanel();
        pnlBotao = new JPanel();
        lblCampo1 = new JLabel("Campo1:");
        lblCampo2 = new JLabel("Campo2:");
        txtCampo1 = new JTextField(20);
        txtCampo2 = new JTextField(20);
        botao = new JButton("Funcao");

        pnlCampo1.add(lblCampo1);
        pnlCampo1.add(txtCampo1);

        pnlCampo2.add(lblCampo2);
        pnlCampo2.add(txtCampo2);

        pnlBotao.add(botao);

        botao.addActionListener(new  ActionListener() {
            public void actionPerformed(ActionEvent e) {
                model.atualizar(txtCampo1.getText(), Integer.parseInt(txtCampo2.getText()));
            }
        });

        this.setLayout(new GridLayout(3,1));
        this.add(pnlCampo1);
        this.add(pnlCampo2);
        this.add(pnlBotao);

        this.setSize(300,300);
        this.setVisible(true);
    }

    public void update(Observable o, Object arg) {
        this.setVisible(false);
    }
}

A classe Controller implementa Observer, ou seja, ela será notificada quando houver qualquer mudança na classe View (Observable) tem em seu método update() a exibição dos dados populados na classe View, sendo este método invocado quando o estado da Observable foi modificado.

Código da Classe Controller:

import java.util.Observable;
import java.util.Observer;

public class Controller implements Observer {
    private Model model;
    private View view;

    public static void main(String[] args) {
       new Controller();
    }

    public Controller(){
         model = new Model();
         view = new View("Camada Visão", model);

         model.addObserver(this);
         model.addObserver(view);
    }

    public void update(Observable o, Object arg) {
        System.out.println("O modelo contém os seguintes dados:");
        System.out.println("Campo 1:"+ model.getCampo1());
        System.out.println("Campo 2:"+ model.getCampo2());
    }
}

Resumo

1) Classes que serão Observadas:

Estender java.util.Observable;

Adicionar Observadores (addObserver());

Avisar mudança com notifyObservers() e setChanged();

2) Classes que serão atualizadas quando houver mudança, Observadoras:

Implementar a interface java.util.Observer();

Codificar o método update();

Desta forma quando a classe observada “avisar” uma mudança, todas as observadores disparam seus códigos de atualização.

Próximos artigos virão, obrigado pela leitura. Qualquer dúvida ou sugestão, favor postar!!!

Referências:

FREEMAN E.; FREEMAN. E; SIERRA, K.; BATES B. Head First: Design Patterns. Sebastopol: O’Reilly, 2001.



Comentários

3 comentários em “Design Pattern Observer com aplicação Swing (JSE)

  1. Boa noite Sylvio,

    Eu também tenho interesse no post.
    Por favor se puder passar o resto dele para o meu e-mail, ficarei grata.

    Seu tutorial foi o melhor que achei, ao meu ver.

    Obrigada..!!
    Lilian Mendes