Implementando correctamente el patrón MVC en el desarrollo de la GUI utilizando Swing en Java

En primer lugar, vengo de una gran experiencia en PHP con MVC, cuando comencé con PHP, navegué muchas veces, hice mi mejor esfuerzo y perfeccioné mi diseño MVC-Like en PHP. Muchas personas respondieron con respuestas que me ayudaron mucho.

Pero después de iniciar el desarrollo de GUI en Swing, las respuestas sobre MVC en Swing son totalmente diferentes. Por ejemplo, ¿un modelo también es una vista? De acuerdo con las sugerencias de Oracle, TextElementModel no tiene ningún negocio lógico aquí, todo lo que hace es marcar (establecer el color, etc.) y establecer datos, como establecer texto, etc. Cuando desarrollé en PHP, no existe nada parecido a AbstractModel porque siempre me dijeron que un modelo no es una clase, o más, es una capa completa que procesa negocios lógicos.

En PHP utilicé Services, Data Mappers y Domain Objects, sugerido por esta sorprendente respuesta que me ayudó mucho en PHP: ¿cómo debería estructurarse un modelo en MVC?

Mi bash

Después de leer nuevamente, pensé en probarlo y hacer algo similar en Java:

Tengo ControllerContainer que crea todos los 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 puede ver, agrego la vista llamada “prueba” con instancia de ViewTest al controlador, ahora estará visible en el marco y puede tomar entrada.

Mi clase de Controller , que debe ser abstracta, pero no la resumí aún:

 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); } } 

Y un controlador de prueba:

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

Y mi 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); } } 

El problema

Como ve, mi vista crea un nuevo botón y le agrega un oyente de mouse. el oyente tendrá acceso al controlador para pasar la entrada. El controlador recibe la entrada y cambia la vista.

Básicamente, el controlador forzó instantáneamente a actualizar la vista, sin ningún tipo de problema lógico serio porque no es necesario en mi caso.

De acuerdo con el enlace que he publicado anteriormente, respondido por tereško, ¿cómo puedo usar su idea y sugerencias con Java Swing correctamente?

Estoy realmente confundido, después del fondo de PHP.

Tal vez estoy malentendido y todo debe hacerse de manera diferente en diferentes idiomas? Pero pensé que los patrones siempre deberían implementarse de la misma manera.

Si necesita más información, hágamelo saber.

Tal vez estoy malentendido, y todo debe hacerse de manera diferente en diferentes idiomas?

No hay malentendidos; el patrón simplemente se aplica de manera diferente.

Como se señala en un comentario de @ordous y esta respuesta por @udalmik, una aplicación Swing puede tener múltiples implementaciones del patrón MVC . Como se señala aquí y aquí , “no todas las interacciones deben pasar por el controlador de su aplicación”. Por el contrario, una aplicación web puede “tener una relación 1: 1 entre vistas y controladores”.

La architecture de modelo separable de Swing, citada aquí , “colapsa la vista y las partes del controlador de cada componente en un único objeto UI (interfaz de usuario)”. Los controladores Swing están dispersos entre los descendientes de JComponent , generalmente en el delegado de UI del componente. Como ejemplo concreto, BasicButtonUI contiene un BasicButtonListener que maneja la interacción del usuario con el mouse.

Casi utilizo la respuesta en el enlace, pero el hecho de que su controlador se extiende JPanel arruinó, me confundió totalmente allí.

Esto puede ser confuso, ya que un simple progtwig Swing puede no tener controlador explícito en absoluto. Como se sugiere en este esquema , el controlador tiene acceso directo a cualquier vista y modelo relevante; también puede escuchar la interacción del usuario con la vista. El ejemplo fue diseñado para ilustrar la interacción más simple. Es mera coincidencia que el efecto sea evocado por la interacción del usuario con un componente de vista. La simulación citada aquí , por ejemplo, tiene un ControlPanel de vista de componentes que actualiza la vista y el modelo de la aplicación. DisplayPanel escucha directamente un ComponentEvent que requiere una actualización de modelo. Etc.

El controlador de su aplicación es entonces libre de enfocarse en las necesidades de la aplicación.

@ Marco13 profundiza sobre esto y cita ejemplos adicionales en esta respuesta relacionada.

El patrón MVC es un paradigma común, por lo que no hay diferencias entre los lenguajes de progtwigción en general. Sin embargo, la implementación y algunas terminologías a veces se ven diferentes. En Java Swing es a menudo ver dos enfoques siguientes:

1. Classic MVC

Controlador : escucha las acciones de la interfaz de usuario y realiza las actualizaciones correspondientes del modelo . Puede escuchar acciones desde diferentes Vistas .

Modelo : representa el estado y la lógica del dominio, métodos para modificar el estado. Notifica a los oyentes acerca de las actualizaciones del modelo ( varias Vistas pueden escuchar las actualizaciones). El modelo es independiente y no sabe nada sobre los oyentes y su lógica.

Ver : es responsable de la interfaz de usuario, el diseño de los elementos de la interfaz de usuario, también escucha las actualizaciones del modelo y actualiza la interfaz gráfica si es necesario. Tiene algún conocimiento sobre el modelo; en el ejemplo que se muestra a continuación, sabe cómo procesar la lista de “elementos”.

El diseño de una aplicación “To Do” simple puede verse así:

enter image description here

2. MVP (Presentador de vista de modelo)

El controlador actúa como un Mediador entre la Vista y el Modelo . La vista se vuelve muy delgada y no sabe nada sobre el Modelo e interactúa solo con el Controlador . El controlador escucha tanto la vista como el modelo y realiza las acciones correspondientes.

enter image description here

Swing agrega cierta confusión porque usa el patrón MVC para sus componentes de UI. Cada control de UI tiene un modelo y una vista. Hace más fácil diseñar nuevos componentes de interfaz de usuario, sin embargo, en una “gran imagen” de todo el diseño de la aplicación: los controles de interfaz de usuario permanecen en la capa de visualización.