MVC - Implementação

Olá pessoal do GUJ!

Sou novato aqui, e em Java também(estudo Java há pouco menos de 1 ano), e este fórum já tem me ajudado muito em minhas pesquisas ultimamente.
Indo direto ao assunto, estou com algumas dúvidas quanto ao Pattern MVC (sei que já devem estar cheios disso, pois já li dezenas de tópicos sobre esse assunto, porém, nenhum tirou minhas dúvidas).

Primeiro, colocar o que entendi sobre o assunto até agora:

Controller

-Define o comportamento da aplicação
-Mapeia as ações do usuário para atualização do modelo
-Seleciona a view para saida de dados
-Um controller para cada funcionalidade (?)

View

-Fornece dados ao model (será mesmo?)
-Faz requisições (para o modelo) de atualizações no modelo (quando o modelo é acessado e seu estado é modificado)
-Envia ações (eventos) para o controller (será mesmo)
-Permite a seleção da view apropriada por parte do controller

Model

-Encapsula o estado da aplicação (?)
-Responde a consultas (vindas da view de estado do modelo (?))
-Expõe a funcionalidade da aplicação (regras de negócios?)

FONTE: http://desenvolvendoaplicacoeseamente.files.wordpress.com/2009/12/mvc-structure-generic.gif

Ou seja: o usuário interage com a view, que manda a ação para o controller, que atualiza o model de acordo com a requisição, o model notifica a view sobre a alteração no seu estado, e a view (através de métodos) atualiza a sua interface gráfica.

Agora as dúvidas:

É exatamente isso o que acontece ou estou falando bobeira?

O controller não precisará saber de onde veio a ação (através de listeners), a própria view instanciará o controller e, ocorrendo a ação, dentro do evento da view passo ao controller o que fazer, ou como alterar o model?

Como eu faria para o model notificar a view sobre alterações em seu estado?

Li em alguns posts do sergiotaborda por aqui, e se entendi bem, a view pode se atualizar pegando os atributos do model. É assim mesmo?

Não quero nada pronto e mastigado aqui não, porém, quando houver necessidade, exemplos serão sempre muito bem vindos.

Conto com a ajuda de vocês, e esperarei as primeiras respostas para poder prosseguir com o tópico.

Muito obrigado desde já! Um grande abraço a todos!

Olá,

Quanto as suas colocações referentes as camadas de controle, visão e persistência, eu não tenho nenhuma objeção, não sei os demais amigos do fórum.

Eu aconselho você a dar uma sapiada naquela apostila da caelum, a fj21, tem vários exemplos de aplicações cliente/servidor, no meu caso, foi de grande ajuda: tanto no âmbito de arquitetura quanto no de desenvolvimento.

Fica ai a dica, espero ter ajudado!

[]'s

Olá getAdicted,

Vou ler a apostila, muito obrigado pela dica!
Só uma outra pergunta: tem diferenças entre a implementação entre o MVC pra web e o desktop? Pq já li sobre o MVC2 aqui, em que diziam ser pra web, e também algumas recomendações da sun que diziam o mesmo.

Muito obrigado pela participação, getAdicted!

Olá novamente amigo,

Eu sempre mantive contato com aplicações cliente/servidor, somente, seja através do GUJ, seja através de apostilas (também disponibilizadas pelos companheiros), entretanto, em uma breve pesquisa que eu fiz logo após você postar, conclui que esse padrão de arquitetura também é empregado em aplicações Desktop:

http://www.guj.com.br/posts/list/60570.java

Se os demais amigos postarem nesse tópico, poderão lhe informar melhor. :smiley:

[]'s

getAdicted , em primeiro lugar muito obrigado por disponibilizar parte do seu tempo para me ajudar.

Então, já dei uma lida aqui no forum tmb, e encontrei algumas informações sim.
Li alguns exemplos teóricos sobre implementação do MVC em sistemas web, o que já deu uma boa clareada.

Porém, para desktop (o que necessito), funciona de maneira um pouco diferente, já que nesse caso, o MVC trabalha de forma tringular (view -> controller -> model -> view).
Contudo, claro que terei que fazer algum pequeno sistema web (para estudos), tentando usar o mesmo model futuramente, já que, pelo que entendi, MVC serve justamante para isso: ter o mesmo model sendo usado em vários ambientes, como web, desktop etc.
Tô certo ou falando bobeira?

Novamente muito obrigado pela atenção e ajuda!

Abraços!

Encontrei um ótimo material sobre patterns, estou estudando nesse momento.
Quem quiser dar uma olhada: http://www.patterndepot.com/put/8/DesignJava.PDF

Abraços!

Olá pessoal.

Estou estudando o pattern Observer(para utilização com MVC), porém, estou encontrando muitas, dificuldades.
A idéia é a seguinte:

Tenho 3 classes:
Model: possui o atributo texto(String) que herda Observable
View1: possui um JFrame com um Jtxt(txtTexto) e um Jbtn(btnAlterar)
View2: possui um JFrame com u JLabel(lblTexto)

O que estou tentando fazer: Quando btnAlterar da View1 for clicado, pegar o valor de txtTexto e mandá-lo para o atributo texto de Model, que ao receber o valor, informa a View2 que seu estado(do Model) foi alterado, e exibindo
o valor do atributo texto de Model na View2 .

Abaixo segue o código para entenderem melhor:

Model

package observercomheranca;

import java.util.Observable;

public class Model extends Observable{

    /*variável que será passada por View1 e recebida por View2*/
    private String texto = "";


    /*Getter e Setter*/
    public String getTexto() {
        return texto;
    }

    public void setTexto(String texto) {
        this.texto = texto;
        setChanged();
        notifyObservers();
    }

}

View1

package observercomheranca;

import javax.swing.*;

/*janela que terá um txt e um btn, que, quando clicado no btn, enviará o texto
 para o Model, que enviará aos seus observadores*/
public class View1 {
    
    private JFrame janela = new JFrame();
    private JPanel painel = new JPanel();

    private JTextField txtTexto = new JTextField();
    private JButton btnAlterar = new JButton("Alterar");

    public View1() {
        txtTexto.setColumns(15);

        painel.add(txtTexto);
        painel.add(btnAlterar);

        janela.add(painel);
        janela.setResizable(false);
        janela.setLocation(800, 450);

        janela.pack();
        janela.setVisible(true);
    }

    public static void main(String[] args) {
        View1 v1 = new View1();
    }



    public String getTexto() {
        return txtTexto.getText();
    }

    public void setTxtTexto(String texto) {
        this.txtTexto.setText(texto);
    }

}

View2

package observercomheranca;

import javax.swing.*;

/*janela que possui apenas uma label para receber o valor digitado no txt
 de View1*/
public class View2 {

    private JFrame janela = new JFrame();
    private JPanel painel = new JPanel();

    private JLabel lblTexto = new JLabel(" ");

    public View2() {
        painel.add(lblTexto);

        janela.add(painel);
        janela.setResizable(false);
        janela.setLocation(800, 450);
        janela.setSize(200, 200);

        janela.pack();
        janela.setVisible(true);
    }

    public static void main(String[] args) {
        View2 v2 = new View2();
    }



    public String getTexto() {
        return lblTexto.getText();
    }

    public void setTxtTexto(String texto) {
        this.lblTexto.setText(texto);
    }


}

Não quero nada pronto, apenas que me me ajudem com dicas, pois não estou conseguindo entender muita coisa, mesmo pesquisando até a documentação do Java.
Estou me esforçando pra aprender alguns design patterns, conto com a ajuda de vocês para conseguir me virar com esse.

Abraços a todos e muito obrigado desde já!

lembrei de uma discussão sobre o assunto que li aqui no fórum.

http://www.guj.com.br/posts/list/129277.java

Boa tarde wbdsjunior,

Primeiramente, muito obrigado pela colaboração!

Então, li praticamente o tópico todo (apesar do tamanho dele ser monstruoso, já havia lido parte ele, e agora li mais um bom trecho), e pra essa dúvida atual quanto ao observer não me tirou as dúvidas ainda.

Vou continuar procurando por algo aqui no fórum e pelo google tmb.

Novamente muito obrigado!

Continuo esperando a colaboração do pessoal, abraços!

Pelo que tô entendo:

Meu model tem que herdar Observable, chamando os métodos setChanged() e notifyObservers() quando algo for alterado no próprio model.
Depois, cada observador deve implementar Observer, sobrescrevendo o método abstrato update() para atualizar o modelo.

É isso mesmo?

Acho que estou começando a entender como funciona, só está um pouco dificil de implementar.

Vou continuar tentando por aqui.

Obrigado, abraços!

O método update do Observer é chamado quando há uma atualização no Observable. É sua responsabilidade atualizar o Observer baseado na atualização do Observable. Se Observer é uma tela, vc atualizaria com o estado mais recente do Observable.

esmiralha, muito obrigado por me ajudar!

Então, pelo que entendi, o update deve ser feito quase “no braço”, é isso?

Consegui o seguite:

No model:

/*add observer já na instanciação*/
public Model(Observer obs){
        this.addObserver(obs);
    }
    /*atualiza o valor da variável texto e notifica observers*/
    public void atualizar(String texto){
        this.texto = texto;
        setChanged();
        notifyObservers(texto);
    }

Na View2

/*add observador */
Model model = new Model(this);

public View2() {

        painel.add(lblTexto);

        janela.add(painel);
        janela.setResizable(false);
        janela.setLocation(800, 450);
        janela.setSize(200, 200);

        janela.pack();
        janela.setVisible(true);


        model.atualizar("TESTE");
    }
/*aqui atualizo a lblTexto da View2 com o valor da variável texto do model*/
public void update(Observable o, Object texto) {
       if (o instanceof Model){
           lblTexto.setText((String)texto);
       }

Tá correto ai, ou é muita gambiarra? Lembrando que estou apenas tentando entender como funciona, pra depois pra poder implementar de forma correta.

Novamente, muito obrigado pela ajuda!

Abraços!

Certo está, mas leia esse artigo aqui: http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/arqu/observer.htm

esmiralha, muito obrigado pelo link!

Dei uma lida por cima agora (tenho que ir à aula daqui a pouco), e pelo que entendi, essa é a forma correta de trabalhar com Observer(usando interfaces e tal).
Ainda hoje estarei lendo com mais tempo.

Novamente muito obrigado pela ajuda!

Abraços!

Pessoal, consegui da forma que segue abaixo:

Model

package observercomheranca;

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

public class Model extends Observable{

    /*variável que será passada por View1 e recebida por View2*/
    private String texto = "";

    public Model(Observer obs){
        this.addObserver(obs);
    }

    /*Getter e Setter*/
    public String getTexto() {
        return texto;
    }


    public void atualizar(String texto){
        this.texto = texto;
        setChanged();
        notifyObservers(texto);
    }


}

View1

package observercomheranca;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.*;

/*janela que terá um txt, que, recebendo entradas via teclado, enviará o texto
 para o Model, que enviará aos seus observadores*/
public class View1 implements Observer{

    Model model = new Model(this);

    private JFrame janela = new JFrame();
    private JPanel painel = new JPanel();

    private JTextField txtTexto = new JTextField();

    public View1() {

        /*passa o model de View1 para View2 como parametro ao instanciar View2
         para ambos poderem trabalhar com a mesma instancia de model*/
        View2 v2 = new View2(model);


        /*add keylistener para quando a tecla for liberada passar o seu valor
         para o atributo texto pertencente a model*/
        txtTexto.addKeyListener(new KeyListener() {

            public void keyTyped(KeyEvent e) {
               
            }

            public void keyPressed(KeyEvent e) {
                
            }

            public void keyReleased(KeyEvent e) {
                model.atualizar(txtTexto.getText());
            }
        });

        txtTexto.setColumns(15);

        painel.add(txtTexto);

        janela.add(painel);
        janela.setResizable(false);
        janela.setLocation(800, 450);

        janela.setLocation(800, 450);

        janela.pack();
        janela.setVisible(true);
    }

    public static void main(String[] args) {
        View1 v1 = new View1();
    }

    public void update(Observable o, Object arg) {
        /*aqui entraria algum código caso uma atualização do model
         devesse causar algum impacto nesta classe*/
    }


}

View2

package observercomheranca;

import java.util.Observable;
import java.util.Observer;
import javax.swing.*;

/*janela que possui apenas uma label para receber o valor digitado no txt
 de View1*/
public class View2 implements Observer{

    /*precisamos de um model para poder registrar View2 como observer
     então primeiramente passamos um model vazio*/
    Model model = null;

    private JFrame janela = new JFrame();
    private JPanel painel = new JPanel();

    private JLabel lblTexto = new JLabel(" ");

    public View2(Model model) {

        /*como View1 chamará View2, passamos o model da View como parametro
         para View2 quando esta última for instanciada, para poder reistrá-la
         como observer*/
        this.model = model;

        /*registra View2 como observer de model*/
        model.addObserver(this);

        painel.add(lblTexto);
        
        janela.add(painel);
        janela.setResizable(false);
        janela.setLocation(800, 450);
        janela.setSize(200, 200);

        janela.setLocation(650, 450);

        janela.pack();
        janela.setVisible(true);
    }

    /*aqui atualizo a lblTexto da View2 com o valor da variável texto do model*/ 
    /*aqui o Object seria o próprio Model instanciado? */
    public void update(Observable o, Object texto) {
       if (o instanceof Model){
           lblTexto.setText((String)texto);
       }
    }
}

Pelo link passado por vc esmiralha, pude perceber que é uma gambiarra e das fortes o que fiz, rs.
Porém, também gostaria de saber se meus conceitos inseridos como comentários no código estão corretos ou não?
Minha maior dúvida: aqui o Object texto seria o próprio Model instanciado, correto? Já que o instanceof Model retorna true.

/*aqui o Object seria o próprio Model instanciado? */ public void update(Observable o, Object texto) { if (o instanceof Model){ lblTexto.setText((String)texto); }

Porém, como ele é uma instancia de Model, como o seu cast para String com (String)texto, retorna o valor do atributo texto do objeto Model?

Críticas são muito bem vindas, estou aqui justamente tentando aprender, com a grande ajuda de vocês, é claro!

Abraços!

Olá pessoal, dei uma sumida, muita correria, mas não deixei o Java de lado!

Implementei o padrão observer para adequar um de meus projetos da faculdade ao MVC, e fiz da seguinte maneira:

Criei duas interfaces: Observer e Observable

Observable.java

public interface Observable {
    
    public void addObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();
    
}

Observer.java

package interfaces;

public interface Observer {

    public void update();

}

A cada classe de modelo que tenho no projeto, tenho que implementar a interface Observable, pra isso crio uma lista de observadores que, quando alterado algum atributo do modelo, chama notifyObservers(), percorrendo a lista e notificando os observadores sobre a atualização no modelo

A view implementa a interface Observer, definindo o método update(). Neste método, a view atualiza a sua interface de acordo com a sua instancia do modelo.

Pelo que podem ver, é uma implementação muito simples do pattern Observer, mas já é um começo.
Pelo esquema UML do pattern, parece estar tudo certo, porém, venho pedir a opinião de vocês sobre essa implementação, o que devo mudar, se tem algo errado, qualquer coisa.
Quero realmente aprender este pattern para poder dar seguimento ao meu estudo sobre MVC, e ficarei muito grato a quem puder me ajudar.

Um grande abraço a todos!

Olá pessoal!

Bem, continuando com as minhas dúvidas (que agora começam a ser poucas), quero saber o seguinte:

O controlador recebe o modelo, para tratamento dos dados enviados pelo usários via visão, até ai entendi tudo perfeitamente.

O que gostaria de saber é: a visão também deve receber o modelo? Isto é, deve haver mesmo uma referência ao modelo dentro da visão?

Já agradeço antecipadamente por quem puder ajudar!

Abraço a todos.

Outra pergunta: qual o real papel do controlador?

Quanto mais pesquiso, mais encontro pessoas com conceitos diferentes quanto ao papel do controlador, me deixando mais confuso ainda.

Só lembrando que estou me empenhando ao máximo para aprender sobre mvc, mas nunca vi algo tão complicado de encontrar definições(até encontro algumas, mas são genéricas a tal ponto que não consigo entender).

Ficarei muito grato caso alguem possa me ajudar.

Um grande abraço a todos!

Olá pessoal, eu aqui novamente!

Em primeiro lugar, deixar claro que não eestou tentando “floodar” por aqui, tanto que agora venho agora apenas postar algo que achei ser o verdadeiro conceito sobre o controlador neste link http://www.enode.com/x/markup/tutorial/mvc.html

Já pesquisei muito aqui no fórum e realmente vi muitos feras dizerem que o Swing usa MVC, e neste artigo isso fica bem claro, um componente com os componente gráficos para receber o valor, para aumentar e decrementar esse mesmo valor, ou seja:

Visão é o próprio componente gráfico e o Modelo é atualizado (pelo Controlador) de acordo com a seta clicada na componente gráfico (aumenta ou decrementa o valor no Modelo).

Acho que agora começa a clarear a idéia aqui, já que neste mesmo artigo diz que o controlador usar listeners para saber como agir e atualizar o Modelo de acordo com entrada.

É isso mesmo ou estou falando bobagem?

Muito obrigado a todos que já participaram e aos que leem com atenção o tópico!

Um abração a todos!

Esse tutorial foi muito esclarecedor pra mim (apesar de ser de 2007). Acessa ele e vê se te ajuda.

http://www.oracle.com/technetwork/articles/javase/mvc-136693.html

No fim do tutorial você pode baixar o fonte todo e também existem alguns links para outros sites que explicam de forma
bem esclarecedora esse pattern.