El patrón composite MVC
Introducción al problema
La realización de la interfaz de usuario de una aplicación resulta un problema complejo. La principal característica del diseño de una interfaz de usuario es que debe ser lo suficientemente flexible para dar respuesta a las siguientes exigencias, propias de una interfaz moderna:
-
Los usuarios de la aplicación pueden solicitar cambios a dicha interfaz para que sea más eficaz o fácil de usar.
-
La aplicación puede ofrecer nuevas funcionalidades, lo cual requiere una actualización de su interfaz de usuario.
-
El sistema de ventanas de la plataforma con el que trabaja la aplicación puede evolucionar e imponer modificaciones en la interfaz de usuario.
-
La misma información puede representarse mediante diferentes vistas e introducirse a través de distintos medios.
-
La representación debe reflejar, inmediatamente, las modificaciones de datos manipulados por la aplicación.
-
Los datos gestionados por la aplicación pueden manipularse simultáneamente a través de varias interfaces: por ejemplo, una interfaz de usuario de escritorio y una interfaz de usuario web.
Estos requisitos hacen casi imposible diseñar una interfaz de usuario que pueda aplicarse en el seno del núcleo funcional de la aplicación. Conviene adoptar, por lo tanto, una solución algo más modular como la que propone el patrón composite...
El patrón composite MVC
Los autores de Smalltalk-80 proponen una solución a este problema llamada MVC, del acrónimo Model-View-Controller, que preconiza la siguiente separación entre componentes de una aplicación:
-
Model (modelo): se trata del núcleo funcional que gestiona los datos manipulados en la aplicación.
-
View (vista): se trata de los componentes destinados a representar la información al usuario. Cada vista está vinculada con un modelo. Un modelo puede estar vinculado a varias vistas.
-
Controller (controlador): un componente de tipo controlador recibe los eventos que provienen del usuario y los traduce en consultas para el modelo o para la vista. Cada vista está asociada a un controlador.
El vínculo entre el modelo y una vista se realiza aplicando el patrón Observer, que hemos estudiado en el capítulo El patrón Observer dedicado al mismo. En este patrón, el modelo constituye el sujeto y cada vista es un observador. De este modo, cada actualización de datos que gestione el núcleo funcional genera una notificación a las distintas vistas. Éstas pueden, entonces, actualizar la información que muestran al usuario.
La estructura genérica, en su forma simplificada, de MVC se representa mediante la notación UML de la figura 5-3.1. El modelo se incluye como el sujeto del patrón Observer y, por lo tanto, como una subclase de la clase abstracta Sujeto. La clase Modelo implementa dos métodos: getDatos y modificaDatos. El primero permite acceder a los datos del modelo y el segundo modificarlos. En la práctica, estos métodos darán un acceso más fino a los datos del modelo, así como a los servicios que implementan las funcionalidades de la aplicación.
La clase Vista se incluye como observador del modelo. El método actualiza se invoca cuando se quiere actualizar los datos del modelo. La vista extrae del modelo los datos que se quieren visualizar y los representa. Además del método actualiza, la vista posee el método manipulaRepresentación destinado al controlador. En efecto, algunas acciones del usuario no tendrán ninguna consecuencia sobre el modelo sino, únicamente, sobre la representación: mover una ventana, alguna acción sobre la barra...
El framework Vaadin
El ejemplo presentado a continuación se basa en el framework Vaadin (http://www.vaadin.com). Vaadin es un framework Java especialmente concebido para escribir servlets. Integra el soporte de la comunicación AJAX entre el navegador web y el servlet, permitiendo, de este modo, crear una aplicación rica e interactiva.
Lo más importante es la simplicidad del desarrollo con Vaadin: no requiere tener ningún conocimiento acerca de HTML, desarrollo de servlets o incluso JavaScript para realizar una aplicación. En efecto, el desarrollo de la interfaz de usuario de una aplicación web con Vaadin se realiza de forma similar al desarrollo de una interfaz de usuario para una aplicación de escritorio con Swing (o AWT, o incluso SWT). El único lenguaje que es necesario conocer es el lenguaje Java.
La figura 5-3.4 ilustra la arquitectura general de Vaadin. Vaadin está formado por dos elementos, a saber, un motor JavaScript del lado cliente y un conjunto de componentes de interfaz de usuario del lado servidor. En efecto, de manera similar a Swing, el framework Vaadin está compuesto por componentes de interfaz. El motor del lado cliente se encarga de crear y gestionar la interfaz de usuario en el seno del navegador web. Los componentes de interfaz del lado servidor se comunican con la aplicación Java.
Dicha arquitectura permite liberar a la aplicación Java de todos los problemas...
Ejemplo en Java
1. Introducción
El ejemplo consiste en una pequeña base de datos de vehículos que está disponible en modo de sólo consulta. Existe un menú desplegable en la parte superior de la vista que ofrece la posibilidad, al usuario, de seleccionar el vehículo que quiere visualizar. Se muestran, entonces, la marca, el modelo y el precio del vehículo seleccionado. El botón Anuncio siguiente permite ver el siguiente anuncio relativo al mismo vehículo. Si el usuario pulsa dicho botón una vez mostrado el último anuncio, la interfaz vuelve a mostrar el primer anuncio.
La figura 5-3.5 muestra la interfaz de usuario. Se ejecuta, tal y como hemos indicado, en un navegador web.
Figura 5-3.5 - Interfaz de usuario de la base de datos de vehículos
2. Arquitectura
La figura 5-3.6 muestra la arquitectura del ejemplo y muestra una implementación basada en el patrón MVC. La clase BaseVehiculos constituye el modelo, la clase VistaPrincipal constituye la vista central compuesta de varias vistas anidadas que son widgets nativos de Vaadin (widgets HTML) y las dos clases ControladorMenuSeleccion y ControladorBotonAnuncioSiguiente representan los dos controladores asociados cada uno a una vista.
Figura 5-3.6 - Arquitectura del ejemplo
Comprobamos que se han aplicado los patrones Observer para el modelo, Composite para la vista principal, que es una vista compuesta en Vaadin (y que implementa la misma interfaz Componente que sus vistas anidadas), y Strategy para el controlador. No obstante, en este último no es posible factorizar a nivel de la clase abstracta Controlador el método de gestión de eventos, puesto que no es el mismo para ambos widgets NativeButton (botón) y NativeSelect (menú desplegable). Conviene, también, destacar que ambos controladores se incluyen como oyentes (listeners) de los widgets para que puedan administrar las acciones del usuario.
3. Estudio del código
Comenzamos el estudio del código por las clases Sujeto y BaseVehiculos. La clase Sujeto no presenta ninguna particularidad, gestiona una lista de observadores y, cuando se produce una llamada al método notifica, solicita a cada observador de la lista que se actualice.
La clase BaseVehiculos constituye el modelo de la aplicación. La base contiene vehículos, que son los elementos de la tabla vehiculos. Están...