Implementando Corretamente o Padrão MVC no Desenvolvimento da GUI Usando o Swing em Java

Primeiramente, eu venho de um grande background em PHP com MVC, quando eu comecei com PHP, eu viajei várias vezes, para dar o meu melhor e aperfeiçoar meu design MVC-Like em PHP. Muitas pessoas gostam de responder com respostas que me ajudaram muito.

Mas depois de iniciar o desenvolvimento da GUI no Swing, as respostas sobre MVC no Swing são totalmente diferentes. Por exemplo, um modelo também é uma visão? De acordo com Sugestões da Oracle TextElementModel não tem nenhum negócio lógico aqui, tudo o que faz é marcação (definir cor etc) e configuração de dados como texto definido e assim por diante. Quando eu desenvolvi em PHP, não existe algo como AbstractModel porque sempre me disseram que um modelo não é uma class, ou mais, é uma camada inteira que processa negócios lógicos.

Em PHP eu usei Services, Data Mappers e Domain Objects, sugerido a partir dessa incrível resposta que me ajudou muito no PHP: Como um modelo deveria ser estruturado no MVC?

Minha tentativa

Depois de ler novamente, pensei em dar uma chance e fazer algo similar em Java:

Eu tenho o ControllerContainer que cria todos os controladores:

 public class ControllerContainer { private JFrame frame; public ControllerContainer(JFrame rune) { this.frame = frame; } public void initControllers() { Atest test = new Atest(frame); test.registerView("test", new ViewTest(test)); } } 

Como você vê, eu adiciono a exibição chamada “test” com a instância do ViewTest para o controlador, agora ela estará visível no quadro e poderá receber input.

Minha class Controller , que deve ser abstrata, mas eu não a abstraía ainda:

 public class Controller { private JFrame frame; private Map views = new HashMap(); public Controller(JFrame frame) { this.frame = frame; } protected void registerView(String title, Component c) { this.views.put(title, c); this.frame.add(c); } protected void deregisterView(String title) { this.frame.remove(this.views.get(title)); this.views.remove(title); } protected Component getView(String title) { return this.views.get(title); } } 

E um controlador de teste:

 public class Atest extends Controller { public Atest(JFrame frame) { super(frame); } public void hit() { ((ViewTest) super.getView("test")).changeColorBlue(); } } 

E meu TestView :

 public class ViewTest extends JPanel { private final Atest controller; public ViewTest(Atest c) { this.controller = c; setBackground(Color.RED); setLocation(0,0); setSize(300, 300); setLayout(null); JButton b = new JButton("hello"); b.setSize(150, 150); b.setLocation(0,0); b.addMouseListener(new MouseListener() { @Override public void mouseClicked(MouseEvent arg0) { controller.hit(); } @Override public void mouseEntered(MouseEvent arg0) { } @Override public void mouseExited(MouseEvent arg0) { } @Override public void mousePressed(MouseEvent arg0) { } @Override public void mouseReleased(MouseEvent arg0) { } }); add(b); } public void changeColorBlue() { setBackground(Color.BLUE); } } 

O problema

Como você vê, minha visão cria um novo botão e adiciona um ouvinte de mouse a ele. o ouvinte terá access ao controlador para passar a input. O controlador obtém a input e altera a visão.

Basicamente, o controlador é instantaneamente forçado a atualizar a visão, sem nenhum negócio lógico, porque não é necessário no meu caso.

De acordo com o link que eu postei acima, respondido por tereško, como posso usar a idéia e sugestões dele com o Java Swing corretamente?

Estou muito confuso, depois do background do PHP.

Talvez eu esteja entendendo mal e tudo deve ser feito de forma diferente em diferentes idiomas? Mas eu pensei que os padrões sempre deveriam ser implementados da mesma maneira.

Se você precisar de mais informações, me avise.

   

Talvez eu esteja entendendo mal e tudo deve ser feito de maneira diferente em diferentes idiomas?

Não há mal-entendido; o padrão é meramente aplicado de forma diferente.

Como observado em um comentário por @ordous e esta resposta por @udalmik, um aplicativo Swing pode ter várias implementações do padrão MVC . Como observado aqui e aqui , “nem toda interação precisa passar pelo controlador do seu aplicativo”. Em contraste, um aplicativo da Web pode “ter uma relação de 1: 1 entre visualizações e controladores”.

A arquitetura do modelo separável Swing, citada aqui , “recolhe a visão e as partes do controlador de cada componente em um único object de interface do usuário (interface do usuário)”. Os controladores Swing estão espalhados entre os descendentes do JComponent , normalmente no delegado da UI do componente. Como um exemplo concreto, o BasicButtonUI contém um BasicButtonListener que manipula a interação do mouse do usuário.

Quase usei a resposta no link, mas o fato de seu controlador estender o JPanel estragou tudo, me confundiu totalmente lá.

Isso pode ser confuso, pois um simples programa Swing pode não ter nenhum controlador explícito. Como sugerido neste esboço , o controlador tem access direto a qualquer visão e modelo relevantes; Ele também pode ouvir a interação do usuário com a exibição. O exemplo pretendia ilustrar a interação mais simples. É mera coincidência que o efeito é evocado pela interação do usuário com um componente de visão. A simulação citada aqui , por exemplo, tem um ControlPanel de componentes de exibição que atualizam a visão e o modelo do aplicativo. O DisplayPanel ouve diretamente por um ComponentEvent que requer uma atualização do modelo. Etc.

O controlador do seu aplicativo fica livre para se concentrar nas necessidades do aplicativo.

@ Marco13 elabora sobre isso e cita exemplos adicionais nesta resposta relacionada.

O padrão MVC é um paradigma comum, portanto não há diferenças entre as linguagens de pragramação em geral. No entanto, a implementação e algumas terminologias parecem diferentes. No Java Swing , é comum ver duas abordagens a seguir:

1. Clássico MVC

Controlador – Escuta as ações da interface do usuário, executa as atualizações correspondentes do Modelo . Pode ouvir ações de diferentes modos de exibição .

Modelo – Representa o estado e a lógica do domínio, methods para modificar o estado. Notifica os ouvintes sobre as atualizações do modelo ( vários modos de exibição podem ouvir as atualizações). O modelo é independente e não sabe nada sobre os ouvintes e sua lógica.

Visualização – Responsável pela interface do usuário, layout dos elementos da interface do usuário, também escuta as atualizações do Modelo e atualiza a interface gráfica, se necessário. Tem algum conhecimento sobre o modelo, no exemplo mostrado abaixo ele sabe como processar lista de “itens”.

O design de alguns aplicativos “To Do” simples pode se parecer com:

insira a descrição da imagem aqui

2. MVP (Model View Presenter)

O controlador atua como um mediador entre a vista e o modelo . A visualização fica muito fina e não sabe nada sobre o Modelo e interage apenas com o Controlador . O Controller ouve o View e o Model e executa ações correspondentes.

insira a descrição da imagem aqui

Swing em si adiciona alguma confusão porque usa o padrão MVC para seus componentes de interface do usuário. Cada controle de interface do usuário tem um modelo e exibição. Isso torna mais fácil projetar novos componentes de interface do usuário, no entanto, em uma “grande figura” de todo o design do aplicativo – controles de interface do usuário permanecem na camada de exibição .