¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Java y Eclipse
  3. Modelo MVC
Extrait - Java y Eclipse Desarrolle una aplicación con Java y Eclipse (2a edición)
Extractos del libro
Java y Eclipse Desarrolle una aplicación con Java y Eclipse (2a edición)
1 opinión
Volver a la página de compra del libro

Modelo MVC

Presentación del concepto

El proyecto se ha construido teniendo en cuenta la separación de los objetos de dominio (los datos) de su representación gráfica, y esto desde la fase de análisis.

El modelo MVC (Modelo-Vista-Controlador) es un patrón de arquitectura que formaliza esta separación introduciendo una capa de software intermedia, el controlador.

En un contexto MVC, los datos constituyen los modelos, las clases gráficas las vistas. Modelo y Vista son totalmente independientes el uno del otro: no se conocen. ¿Cómo entonces las acciones que los usuarios realizan sobre las vistas pueden modificar los modelos y a la inversa, cómo pueden mostrarse los datos esperados? Son precisamente los controladores los que se encargaran de este enlace.

Otra particularidad importante: el modelo, si no conoce directamente las vistas que muestran sus datos, tiene al menos la posibilidad de notificar a estas cualquier cambio que les afecte.

images/12eit01.png

El esquema muestra que el usuario no tiene ningún conocimiento del controlador. Sin embargo es el encargado de transmitir de manera transparente para el usuario las peticiones al modelo para su tratamiento. Las vistas se actualizan mediante el modelo a través de un sistema de notificación basado en la noción de eventos y escuchadores de eventos.

Las ventajas de esta arquitectura, que se basa en una separación de responsabilidades, son múltiples:...

MVC y JTable

Las clases ya existentes permiten establecer la conexión con la base de datos y la importación de estos datos en el modelo del dominio de la aplicación.

Se usa un componente Swing de tipo JTable para permitir la representación gráfica de los datos con la forma de una tabla de doble entrada, en filas y columnas.

JTable está construido sobre los principios de la arquitectura MVC, como la mayoría de los componentes Swing que representan datos complejos como las JList y los JTree. Entender los mecanismos utilizados en una JTable facilita el uso de los otros tipos de componentes.

Instanciar un JTable se hace como con cualquier otra clase: basta con llamar a su constructor.

       JTable tabla = new JTable(); 

De momento, la tabla está vacía. Es necesario importar datos en ella.

Para ello, existen varias maneras: proporcionar directamente todos los datos de las filas y columnas en la construcción, proporcionar una lista de objetos que representan cada una una línea de datos, o usar un modelo de tabla. Es esta última opción la elegida para la aplicación.

Gestión de clientes

Se utiliza el paradigma MVC empezando por la gestión de clientes. Los pasos a seguir para los artículos y los pedidos son similares.

1. Modelo del dominio

La clase Cliente es una entidad que pertenece a la M de MVC, el Modelo. Se explicó en el capítulo Entidades.

Su clase asociada ClienteCrud permite realizar operaciones desde la base de datos, entre ellas la búsqueda de clientes.

Aquí tiene la lista de métodos disponibles en la clase ClienteCrud:

images/12eit02.png

La tabla podrá mostrar los clientes que provienen de la base de datos. Para ello, el método leer() de la clase ClienteCrud intervendrá en algún momento.

2. Modelo gráfico

La clase JTable necesita datos para mostrar. La plantilla de la tabla proporciona estos datos, es decir un objeto que implementa la interfaz TableModel. Este modelo de tabla es diferente del modelo de dominio ya que solo concierne el aspecto gráfico.

Este modelo de tabla proporciona al componente gráfico (por lo tanto a la vista):

  • El número de columnas gracias al método getColumnCount().

  • El nombre de las columnas a mostrar con el método getColumnName(int columna), siendo el parámetro el índice de la columna (empezando por 0).

  • El número de filas gracias al método getRowCount().

  • El valor de la celda con el método getValueAt(int fila, int columna), siendo el primer parámetro el índice de la fila, el segundo el de la columna.

  • una manera de añadir escuchadores a este modelo gracias a dos métodos: addTableModelListener y removeTableModelListener.

Proporciona también un medio para editar directamente cualquier celda de la tabla desde la interfaz gráfica gracias a los métodos isCellEditable y setValueAt. No se utilizarán estos métodos en la aplicación.

Se crea un modelo de tabla para los clientes en el package control.modelo.

 Cree una nueva clase llamada ModeloClientes en el package control.modelo. Esta clase hereda de la clase AbstractTableModel que pertenece al package javax.swing.table.

Para acelerar el descubrimiento de la clase AbstractTableModel en el cuadro de diálogo de creación de la clase, puede utilizar el siguiente truco: en el campo Superclass, teclee las mayúsculas de la clase a encontrar, o sea ATM y utilice la combinación de teclas [Ctrl][Espacio]. Eclipse propondrá...

Notificaciones no gráficas

Los conceptos de notificación, eventos y escuchadores no están reservados a las clases gráficas. Es posible utilizar este mecanismo en cualquier parte de una aplicación con unas pocas líneas.

Ponga en marcha esta técnica para la clase ControlCliente, para notificar a cualquier objeto de que se ha modificado un cliente.

 Abra la clase ControlCliente y añada un atributo llamado notificaciones, de tipo java.beans.PropertyChangeSupport:

...   
import java.beans.PropertyChangeSupport;  
...   
public class ControlCliente {  
  
   private final ClienteCrud crud;  
   private final ModeloClientes elModeloClientes;   
  
   private final PropertyChangeSupport notificaciones =   
                   new PropertyChangeSupport(this);  
... 

PropertyChangeSupport es una clase de utilidad de Java que ya posee el código necesario para añadir y quitar escuchadores y generar eventos destinados a estos escuchadores.

 Utilice la opción Source - Generate Delegate Methods... del menú contextual para añadir los métodos addPropertyChangeListener() y removePropertyChangeListener() en la clase ControlCliente.

images/12-13.png
images/12EIT01b.png

Se obtiene entonces el siguiente código:

private final PropertyChangeSupport notificaciones   
                   = new PropertyChangeSupport(this);  
     
public void addPropertyChangeListener(  ...

Estructura y fuentes

La estructura general, la clase ModeloCliente, la clase ControlCliente y las acciones de los botones de los paneles PClientes y la clase PCliente se pueden ver a continuación.

He aquí la estructura general de los packages:

images/12EIT02b.png

1. ModeloClientes

En esta sección encontrará el código fuente de la clase ModeloClientes.

package control.modelo; 
 
/*  
*  Clase que contiene el modelo de datos de Clientes.  
*  Debe extender la clase abstracta AbstractTableModel  
*/ 
 
import java.time.Instant; 
import java.util.ArrayList; 
import java.util.List; 
 
import javax.swing.table.AbstractTableModel; 
 
import entidad.Cliente; 
 
public class ModeloClientes extends AbstractTableModel { 
   private static final long serialVersionUID = 1L; 
 
   // representa las filas del modelo 
   private final List<Cliente> losDatos; 
 
   // los encabezados de las columnas 
   private static final String[] TITULOS = { "Código", "Apellido", 
    "Nombre", "Tarjeta Fidelidad", "Fecha Creación" }; 
 
   public ModeloClientes(List<Cliente> losClientes) { 
       losDatos = new ArrayList<>(losClientes); 
   } 
 
   public int getRowCount() { 
       return losDatos.size(); 
   } 
 
   public int getColumnCount() { 
       return TITULOS.length; 
   } 
 
   public String getColumnName(int columnIndex) { 
       return TITULOS[columnIndex]; 
   } 
 
   // para acceder al valor de una celda 
   public Object getValueAt(int rowIndex, int columnIndex) { 
       Cliente cliente = getCliente(rowIndex); 
       switch (columnIndex) { 
       case 0: 
           return cliente.getCodigo(); 
       case 1: 
           return cliente.getApellido(); 
     ...